/*
 * Copyright (c) 1998, 2013, 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.
 *
 * 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.
 */

/**
 *
 *
 * @author Adrian Colley
 * @author Laird Dornin
 * @author Peter Jones
 * @author Ann Wollrath
 *
 * The rmi library directory contains a set of simple utiltity classes
 * for use in rmi regression tests.
 *
 * NOTE: The JavaTest group has recommended that regression tests do
 * not make use of packages.
 */

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.net.MalformedURLException;
import java.net.ServerSocket;
import java.net.URL;
import java.rmi.NoSuchObjectException;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.RemoteRef;
import java.rmi.server.UnicastRemoteObject;
import java.util.Enumeration;
import java.util.Properties;

import sun.rmi.registry.RegistryImpl;
import sun.rmi.server.UnicastServerRef;
import sun.rmi.transport.Endpoint;
import sun.rmi.transport.LiveRef;
import sun.rmi.transport.tcp.TCPEndpoint;

/**
 * Class of utility/library methods (i.e. procedures) that assist with
 * the writing and maintainance of rmi regression tests.
 */
public class TestLibrary {
    /**
     *                       IMPORTANT!
     *
     * RMI tests are run concurrently and port conflicts result when a single
     * port number is used by multiple tests.  When needing a port, use
     * getUnusedRandomPort() wherever possible.  If getUnusedRandomPort() cannot
     * be used, reserve and specify a port to use for your test here.   This
     * will ensure there are no port conflicts amongst the RMI tests.  The
     * port numbers specified here may also be specified in the respective
     * tests.  Do not change the reserved port numbers here without also
     * changing the port numbers in the respective tests.
     *
     * When needing an instance of the RMIRegistry, use
     * createRegistryOnUnusedPort wherever possible to prevent port conflicts.
     *
     * Reserved port range: FIXED_PORT_MIN to FIXED_PORT_MAX (inclusive) for
     * tests which cannot use a random port.  If new fixed ports are added below
     * FIXED_PORT_MIN or above FIXED_PORT_MAX, then adjust
     * FIXED_PORT_MIN/MAX appropriately.
     */
    public final static int FIXED_PORT_MIN = 60001;
    public final static int FIXED_PORT_MAX = 60010;
    public final static int RMIDVIAINHERITEDCHANNEL_ACTIVATION_PORT = 60001;
    public final static int RMIDVIAINHERITEDCHANNEL_REGISTRY_PORT = 60002;
    public final static int INHERITEDCHANNELNOTSERVERSOCKET_ACTIVATION_PORT = 60003;
    public final static int INHERITEDCHANNELNOTSERVERSOCKET_REGISTRY_PORT = 60004;
    public final static int READTEST_REGISTRY_PORT = 60005;
    private final static int MAX_SERVER_SOCKET_TRIES = 2*(FIXED_PORT_MAX-FIXED_PORT_MIN+1);

    static void mesg(Object mesg) {
        System.err.println("TEST_LIBRARY: " + mesg.toString());
    }

    /**
     * Routines that enable rmi tests to fail in a uniformly
     * informative fashion.
     */
    public static void bomb(String message, Exception e) {
        String testFailed = "TEST FAILED: ";

        if ((message == null) && (e == null)) {
            testFailed += " No relevant information";
        } else if (e == null) {
            testFailed += message;
        }

        System.err.println(testFailed);
        if (e != null) {
            System.err.println("Test failed with: " +
                               e.getMessage());
            e.printStackTrace(System.err);
        }
        throw new TestFailedException(testFailed, e);
    }
    public static void bomb(String message) {
        bomb(message, null);
    }
    public static void bomb(Exception e) {
        bomb(null, e);
    }

    /**
     * Helper method to determine if registry has started
     *
     * @param port The port number to check
     * @param msTimeout The amount of milliseconds to spend checking
     */

    public static boolean checkIfRegistryRunning(int port, int msTimeout) {
        long stopTime = System.currentTimeMillis() + msTimeout;
        do {
            try {
                Registry r = LocateRegistry.getRegistry(port);
                String[] s = r.list();
                // no exception. We're now happy that registry is running
                return true;
            } catch (RemoteException e) {
                // problem - not ready ? Try again
                try {
                    Thread.sleep(500);
                } catch (InterruptedException ie) {
                    // not expected
                }
            }
        } while (stopTime > System.currentTimeMillis());
        return false;
    }

    public static String getProperty(String property, String defaultVal) {
        final String prop = property;
        final String def = defaultVal;
        return java.security.AccessController.doPrivileged(
            new java.security.PrivilegedAction<String>() {
                public String run() {
                    return System.getProperty(prop, def);
                }
            });
    }

    /**
     * Property mutators
     */
    public static void setBoolean(String property, boolean value) {
        setProperty(property, (new Boolean(value)).toString());
    }
    public static void setInteger(String property, int value) {
        setProperty(property, Integer.toString(value));
    }
    public static void setProperty(String property, String value) {
        final String prop = property;
        final String val = value;
        java.security.AccessController.doPrivileged(
            new java.security.PrivilegedAction<Void>() {
                public Void run() {
                    System.setProperty(prop, val);
                    return null;
                }
        });
    }

    /**
     * Routines to print out a test's properties environment.
     */
    public static void printEnvironment() {
        printEnvironment(System.err);
    }
    public static void printEnvironment(PrintStream out) {
        out.println("-------------------Test environment----------" +
                    "---------");

        for(Enumeration<?> keys = System.getProperties().keys();
            keys.hasMoreElements();) {

            String property = (String) keys.nextElement();
            out.println(property + " = " + getProperty(property, null));
        }
        out.println("---------------------------------------------" +
                    "---------");
    }

    /**
     * Routine that "works-around" a limitation in jtreg.
     * Currently it is not possible for a test to specify that the
     * test harness should build a given source file and install the
     * resulting class in a location that is not accessible from the
     * test's classpath.  This method enables a test to move a
     * compiled test class file from the test's class directory into a
     * given "codebase" directory.  As a result the test can only
     * access the class file for <code>className</code>if the test loads
     * it from a classloader (e.g. RMIClassLoader).
     *
     * Tests that use this routine must have the following permissions
     * granted to them:
     *
     *   getProperty user.dir
     *   getProperty etc.
     */
    public static URL installClassInCodebase(String className,
                                             String codebase)
        throws MalformedURLException
    {
        return installClassInCodebase(className, codebase, true);
    }

    public static URL installClassInCodebase(String className,
                                             String codebase,
                                             boolean delete)
        throws MalformedURLException
    {
        /*
         * NOTES/LIMITATIONS: The class must not be in a named package,
         * and the codebase must be a relative path (it's created relative
         * to the working directory).
         */
        String classFileName = className + ".class";

        /*
         * Specify the file to contain the class definition.  Make sure
         * that the codebase directory exists (underneath the working
         * directory).
         */
        File dstDir = (new File(getProperty("user.dir", "."), codebase));

        if (!dstDir.exists()) {
            if (!dstDir.mkdir()) {
                throw new RuntimeException(
                    "could not create codebase directory");
            }
        }
        File dstFile = new File(dstDir, classFileName);

        /*
         * Obtain the URL for the codebase.
         */
        URL codebaseURL = dstDir.toURI().toURL();

        /*
         * Specify where we will copy the class definition from, if
         * necessary.  After the test is built, the class file can be
         * found in the "test.classes" directory.
         */
        File srcDir = new File(getProperty("test.classes", "."));
        File srcFile = new File(srcDir, classFileName);

        mesg(srcFile);
        mesg(dstFile);

        /*
         * If the class definition is not already located at the codebase,
         * copy it there from the test build area.
         */
        if (!dstFile.exists()) {
            if (!srcFile.exists()) {
                throw new RuntimeException(
                    "could not find class file to install in codebase " +
                    "(try rebuilding the test): " + srcFile);
            }

            try {
                copyFile(srcFile, dstFile);
            } catch (IOException e) {
                throw new RuntimeException(
                    "could not install class file in codebase");
            }

            mesg("Installed class \"" + className +
                "\" in codebase " + codebaseURL);
        }

        /*
         * After the class definition is successfully installed at the
         * codebase, delete it from the test's CLASSPATH, so that it will
         * not be found there first before the codebase is searched.
         */
        if (srcFile.exists()) {
            if (delete && !srcFile.delete()) {
                throw new RuntimeException(
                    "could not delete duplicate class file in CLASSPATH");
            }
        }

        return codebaseURL;
    }

    public static void copyFile(File srcFile, File dstFile)
        throws IOException
    {
        FileInputStream src = new FileInputStream(srcFile);
        FileOutputStream dst = new FileOutputStream(dstFile);

        byte[] buf = new byte[32768];
        while (true) {
            int count = src.read(buf);
            if (count < 0) {
                break;
            }
            dst.write(buf, 0, count);
        }

        dst.close();
        src.close();
    }

    /** routine to unexport an object */
    public static void unexport(Remote obj) {
        if (obj != null) {
            try {
                mesg("unexporting object...");
                UnicastRemoteObject.unexportObject(obj, true);
            } catch (NoSuchObjectException munch) {
            } catch (Exception e) {
                e.getMessage();
                e.printStackTrace();
            }
        }
    }

    /**
     * Allow test framework to control the security manager set in
     * each test.
     *
     * @param managerClassName The class name of the security manager
     *                         to be instantiated and set if no security
     *                         manager has already been set.
     */
    public static void suggestSecurityManager(String managerClassName) {
        SecurityManager manager = null;

        if (System.getSecurityManager() == null) {
            try {
                if (managerClassName == null) {
                    managerClassName = TestParams.defaultSecurityManager;
                }
                manager = ((SecurityManager) Class.
                           forName(managerClassName).newInstance());
            } catch (ClassNotFoundException cnfe) {
                bomb("Security manager could not be found: " +
                     managerClassName, cnfe);
            } catch (Exception e) {
                bomb("Error creating security manager. ", e);
            }

            System.setSecurityManager(manager);
        }
    }

    /**
     * Creates an RMI {@link Registry} on a random, un-reserved port.
     *
     * @returns an RMI Registry, using a random port.
     * @throws RemoteException if there was a problem creating a Registry.
     */
    public static Registry createRegistryOnUnusedPort() throws RemoteException {
        return LocateRegistry.createRegistry(getUnusedRandomPort());
    }

    /**
     * Creates an RMI {@link Registry} on an ephemeral port.
     *
     * @returns an RMI Registry
     * @throws RemoteException if there was a problem creating a Registry.
     */
    public static Registry createRegistryOnEphemeralPort() throws RemoteException {
        return LocateRegistry.createRegistry(0);
    }

    /**
     * Returns the port number the RMI {@link Registry} is running on.
     *
     * @param registry the registry to find the port of.
     * @return the port number the registry is using.
     * @throws RuntimeException if there was a problem getting the port number.
     */
    public static int getRegistryPort(Registry registry) {
        int port = -1;

        try {
            RemoteRef remoteRef = ((RegistryImpl)registry).getRef();
            LiveRef liveRef = ((UnicastServerRef)remoteRef).getLiveRef();
            Endpoint endpoint = liveRef.getChannel().getEndpoint();
            TCPEndpoint tcpEndpoint = (TCPEndpoint) endpoint;
            port = tcpEndpoint.getPort();
        } catch (Exception ex) {
            throw new RuntimeException("Error getting registry port.", ex);
        }

        return port;
    }

    /**
     * Returns an unused random port number which is not a reserved port.  Will
     * try up to 10 times to get a random port before giving up and throwing a
     * RuntimeException.
     *
     * @return an unused random port number.
     * @throws RuntimeException if there was a problem getting a port.
     */
    public static int getUnusedRandomPort() {
        int numTries = 0;
        IOException ex = null;

        while (numTries++ < MAX_SERVER_SOCKET_TRIES) {
            int unusedRandomPort = -1;
            ex = null; //reset

            try (ServerSocket ss = new ServerSocket(0)) {
                unusedRandomPort = ss.getLocalPort();
            } catch (IOException e) {
                ex = e;
                // temporarily print stack trace here until we find out why
                // tests are failing.
                System.err.println("TestLibrary.getUnusedRandomPort() caught "
                        + "exception on iteration " + numTries
                        + (numTries==MAX_SERVER_SOCKET_TRIES ? " (the final try)."
                        : "."));
                ex.printStackTrace();
            }

            if (unusedRandomPort >= 0) {
                if (isReservedPort(unusedRandomPort)) {
                    System.out.println("INFO: On try # " + numTries
                        + (numTries==MAX_SERVER_SOCKET_TRIES ? ", the final try, ": ",")
                        + " ServerSocket(0) returned the reserved port "
                        + unusedRandomPort
                        + " in TestLibrary.getUnusedRandomPort() ");
                } else {
                    return unusedRandomPort;
                }
            }
        }

        // If we're here, then either an exception was thrown or the port is
        // a reserved port.
        if (ex==null) {
            throw new RuntimeException("Error getting unused random port. The"
                    +" last port returned by ServerSocket(0) was a reserved port");
        } else {
            throw new RuntimeException("Error getting unused random port.", ex);
        }
    }

    /**
     * Determines if a port is one of the reserved port numbers.
     *
     * @param port the port to test.
     * @return {@code true} if the port is a reserved port, otherwise
     *         {@code false}.
     */
    public static boolean isReservedPort(int port) {
        return ((port >= FIXED_PORT_MIN) && (port <= FIXED_PORT_MAX) ||
                (port == 1099));
    }

    /**
     * Method to capture the stack trace of an exception and return it
     * as a string.
     */
    public String stackTraceToString(Exception e) {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        PrintStream ps = new PrintStream(bos);

        e.printStackTrace(ps);
        return bos.toString();
    }

    /** extra properties */
    private static Properties props;

    /**
     * Returns extra test properties. Looks for the file "../../test.props"
     * and reads it in as a Properties file. Assuming the working directory
     * is "<path>/JTwork/scratch", this will find "<path>/test.props".
     */
    private static synchronized Properties getExtraProperties() {
        if (props != null) {
            return props;
        }
        props = new Properties();
        File f = new File(".." + File.separator + ".." + File.separator +
                          "test.props");
        if (!f.exists()) {
            return props;
        }
        try {
            FileInputStream in = new FileInputStream(f);
            try {
                props.load(in);
            } finally {
                in.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("extra property setup failed", e);
        }
        return props;
    }

    /**
     * Returns an extra test property. Looks for the file "../../test.props"
     * and reads it in as a Properties file. Assuming the working directory
     * is "<path>/JTwork/scratch", this will find "<path>/test.props".
     * If the property isn't found, defaultVal is returned.
     */
    public static String getExtraProperty(String property, String defaultVal) {
        return getExtraProperties().getProperty(property, defaultVal);
    }
}
