import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

/*
 * Copyright 2007 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.
 *
 * 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.
 */


public class Arrrghs{

    /**
     * A group of tests to ensure that arguments are passed correctly to
     * a child java process upon a re-exec, this typically happens when
     * a version other than the one being executed is requested by the user.
     *
     * History: these set of tests  were part of Arrrghs.sh. The MKS shell
     * implementations are notoriously buggy. Implementing these tests purely
     * in Java is not only portable but also robust.
     *
     */

    /* Do not instantiate */
    private Arrrghs() {}

    static String javaCmd;

    // The version string to force a re-exec
    final static String VersionStr = "-version:1.1+";

    // The Cookie or the pattern we match in the debug output.
    final static String Cookie = "ReExec Args: ";

    private static boolean _debug = Boolean.getBoolean("Arrrghs.Debug");
    private static boolean isWindows = System.getProperty("os.name", "unknown").startsWith("Windows");
    private static int exitValue = 0;

    private static void doUsage(String message) {
        if (message != null) System.out.println("Error: " + message);
        System.out.println("Usage: Arrrghs path_to_java");
        System.exit(1);
    }

    /*
     * SIGH, On Windows all strings are quoted, we need to unwrap it
     */
    private static String removeExtraQuotes(String in) {
        if (isWindows) {
            // Trim the string and remove the enclosed quotes if any.
            in = in.trim();
            if (in.startsWith("\"") && in.endsWith("\"")) {
                return in.substring(1, in.length()-1);
            }
        }
        return in;
    }


    /*
     * This method detects the cookie in the output stream of the process.
     */
    private static boolean detectCookie(InputStream istream, String expectedArguments) throws IOException {
        BufferedReader rd = new BufferedReader(new InputStreamReader(istream));
        boolean retval = false;

        String in = rd.readLine();
        while (in != null) {
            if (_debug) System.out.println(in);
            if (in.startsWith(Cookie)) {
                String detectedArgument = removeExtraQuotes(in.substring(Cookie.length()));
                if (expectedArguments.equals(detectedArgument)) {
                    retval = true;
                } else {
                    System.out.println("Error: Expected Arguments\t:'" + expectedArguments + "'");
                    System.out.println(" Detected Arguments\t:'" + detectedArgument + "'");
                }
                // Return the value asap if not in debug mode.
                if (!_debug) {
                    rd.close();
                    istream.close();
                    return retval;
                }
            }
            in = rd.readLine();
        }
        return retval;
    }



    private static boolean doExec0(ProcessBuilder pb, String expectedArguments) {
        boolean retval = false;
        try {
            pb.redirectErrorStream(_debug);
            Process p = pb.start();
            retval = detectCookie(p.getInputStream(), expectedArguments);
            p.waitFor();
            p.destroy();
        } catch (Exception ex) {
            ex.printStackTrace();
            throw new RuntimeException(ex.getMessage());
        }
        return retval;
    }

    /**
     * This method return true  if the expected and detected arguments are the same.
     * Quoting could cause dissimilar testArguments and expected arguments.
     */
    static boolean doExec(String testArguments, String expectedPattern) {
        ProcessBuilder pb = new ProcessBuilder(javaCmd, VersionStr, testArguments);

        Map<String, String> env = pb.environment();
        env.put("_JAVA_LAUNCHER_DEBUG", "true");
        return doExec0(pb, testArguments);
    }

    /**
     * A convenience method for identical test pattern and expected arguments
     */
    static boolean doExec(String testPattern) {
        return doExec(testPattern, testPattern);
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        if (args.length < 1 && args[0] == null) {
            doUsage("Invalid number of arguments");
        }

        javaCmd = args[0];

        if (!new File(javaCmd).canExecute()) {
            if (isWindows && new File(javaCmd + ".exe").canExecute()) {
                javaCmd = javaCmd + ".exe";
            } else {
                doUsage("The java executable must exist");
            }
        }


        if (_debug) System.out.println("Starting Arrrghs tests");
        // Basic test
        if (!doExec("-a -b -c -d")) exitValue++;

        // Basic test with many spaces
        if (!doExec("-a    -b      -c       -d")) exitValue++;

        // Quoted whitespace does matter ?
        if (!doExec("-a \"\"-b      -c\"\" -d")) exitValue++;

        // Escaped quotes outside of quotes as literals
        if (!doExec("-a \\\"-b -c\\\" -d")) exitValue++;

        // Check for escaped quotes inside of quotes as literal
        if (!doExec("-a \"-b \\\"stuff\\\"\" -c -d")) exitValue++;

        // A quote preceeded by an odd number of slashes is a literal quote
        if (!doExec("-a -b\\\\\\\" -c -d")) exitValue++;

        // A quote preceeded by an even number of slashes is a literal quote
        // see 6214916.
        if (!doExec("-a -b\\\\\\\\\" -c -d")) exitValue++;

        // Make sure that whitespace doesn't interfere with the removal of the
        // appropriate tokens. (space-tab-space preceeds -jre-restict-search).
        if (!doExec("-a -b  \t -jre-restrict-search -c -d","-a -b -c -d")) exitValue++;

        // Make sure that the mJRE tokens being stripped, aren't stripped if
        // they happen to appear as arguments to the main class.
        if (!doExec("foo -version:1.1+")) exitValue++;

        System.out.println("Completed Arrrghs arguments quoting/matching tests with " + exitValue + " errors");
        System.exit(exitValue);
    }

}
