207 lines
7.2 KiB
Java
207 lines
7.2 KiB
Java
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);
|
|
}
|
|
|
|
}
|