blob: 8f93df67198ff8922d776f6b64e4dbb7e0fe8c2b [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001import java.io.BufferedReader;
2import java.io.File;
3import java.io.IOException;
4import java.io.InputStream;
5import java.io.InputStreamReader;
6import java.util.ArrayList;
7import java.util.Collection;
8import java.util.Collections;
9import java.util.List;
10import java.util.Map;
11import java.util.StringTokenizer;
12
13/*
14 * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved.
15 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
16 *
17 * This code is free software; you can redistribute it and/or modify it
18 * under the terms of the GNU General Public License version 2 only, as
19 * published by the Free Software Foundation.
20 *
21 * This code is distributed in the hope that it will be useful, but WITHOUT
22 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
23 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 * version 2 for more details (a copy is included in the LICENSE file that
25 * accompanied this code).
26 *
27 * You should have received a copy of the GNU General Public License version
28 * 2 along with this work; if not, write to the Free Software Foundation,
29 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
30 *
31 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
32 * CA 95054 USA or visit www.sun.com if you need additional information or
33 * have any questions.
34 */
35
36
37public class Arrrghs{
38
39 /**
40 * A group of tests to ensure that arguments are passed correctly to
41 * a child java process upon a re-exec, this typically happens when
42 * a version other than the one being executed is requested by the user.
43 *
44 * History: these set of tests were part of Arrrghs.sh. The MKS shell
45 * implementations are notoriously buggy. Implementing these tests purely
46 * in Java is not only portable but also robust.
47 *
48 */
49
50 /* Do not instantiate */
51 private Arrrghs() {}
52
53 static String javaCmd;
54
55 // The version string to force a re-exec
56 final static String VersionStr = "-version:1.1+";
57
58 // The Cookie or the pattern we match in the debug output.
59 final static String Cookie = "ReExec Args: ";
60
61 private static boolean _debug = Boolean.getBoolean("Arrrghs.Debug");
62 private static boolean isWindows = System.getProperty("os.name", "unknown").startsWith("Windows");
63 private static int exitValue = 0;
64
65 private static void doUsage(String message) {
66 if (message != null) System.out.println("Error: " + message);
67 System.out.println("Usage: Arrrghs path_to_java");
68 System.exit(1);
69 }
70
71 /*
72 * SIGH, On Windows all strings are quoted, we need to unwrap it
73 */
74 private static String removeExtraQuotes(String in) {
75 if (isWindows) {
76 // Trim the string and remove the enclosed quotes if any.
77 in = in.trim();
78 if (in.startsWith("\"") && in.endsWith("\"")) {
79 return in.substring(1, in.length()-1);
80 }
81 }
82 return in;
83 }
84
85
86 /*
87 * This method detects the cookie in the output stream of the process.
88 */
89 private static boolean detectCookie(InputStream istream, String expectedArguments) throws IOException {
90 BufferedReader rd = new BufferedReader(new InputStreamReader(istream));
91 boolean retval = false;
92
93 String in = rd.readLine();
94 while (in != null) {
95 if (_debug) System.out.println(in);
96 if (in.startsWith(Cookie)) {
97 String detectedArgument = removeExtraQuotes(in.substring(Cookie.length()));
98 if (expectedArguments.equals(detectedArgument)) {
99 retval = true;
100 } else {
101 System.out.println("Error: Expected Arguments\t:'" + expectedArguments + "'");
102 System.out.println(" Detected Arguments\t:'" + detectedArgument + "'");
103 }
104 // Return the value asap if not in debug mode.
105 if (!_debug) {
106 rd.close();
107 istream.close();
108 return retval;
109 }
110 }
111 in = rd.readLine();
112 }
113 return retval;
114 }
115
116
117
118 private static boolean doExec0(ProcessBuilder pb, String expectedArguments) {
119 boolean retval = false;
120 try {
121 pb.redirectErrorStream(_debug);
122 Process p = pb.start();
123 retval = detectCookie(p.getInputStream(), expectedArguments);
124 p.waitFor();
125 p.destroy();
126 } catch (Exception ex) {
127 ex.printStackTrace();
128 throw new RuntimeException(ex.getMessage());
129 }
130 return retval;
131 }
132
133 /**
134 * This method return true if the expected and detected arguments are the same.
135 * Quoting could cause dissimilar testArguments and expected arguments.
136 */
137 static boolean doExec(String testArguments, String expectedPattern) {
138 ProcessBuilder pb = new ProcessBuilder(javaCmd, VersionStr, testArguments);
139
140 Map<String, String> env = pb.environment();
141 env.put("_JAVA_LAUNCHER_DEBUG", "true");
142 return doExec0(pb, testArguments);
143 }
144
145 /**
146 * A convenience method for identical test pattern and expected arguments
147 */
148 static boolean doExec(String testPattern) {
149 return doExec(testPattern, testPattern);
150 }
151
152 /**
153 * @param args the command line arguments
154 */
155 public static void main(String[] args) {
156 if (args.length < 1 && args[0] == null) {
157 doUsage("Invalid number of arguments");
158 }
159
160 javaCmd = args[0];
161
162 if (!new File(javaCmd).canExecute()) {
163 if (isWindows && new File(javaCmd + ".exe").canExecute()) {
164 javaCmd = javaCmd + ".exe";
165 } else {
166 doUsage("The java executable must exist");
167 }
168 }
169
170
171 if (_debug) System.out.println("Starting Arrrghs tests");
172 // Basic test
173 if (!doExec("-a -b -c -d")) exitValue++;
174
175 // Basic test with many spaces
176 if (!doExec("-a -b -c -d")) exitValue++;
177
178 // Quoted whitespace does matter ?
179 if (!doExec("-a \"\"-b -c\"\" -d")) exitValue++;
180
181 // Escaped quotes outside of quotes as literals
182 if (!doExec("-a \\\"-b -c\\\" -d")) exitValue++;
183
184 // Check for escaped quotes inside of quotes as literal
185 if (!doExec("-a \"-b \\\"stuff\\\"\" -c -d")) exitValue++;
186
187 // A quote preceeded by an odd number of slashes is a literal quote
188 if (!doExec("-a -b\\\\\\\" -c -d")) exitValue++;
189
190 // A quote preceeded by an even number of slashes is a literal quote
191 // see 6214916.
192 if (!doExec("-a -b\\\\\\\\\" -c -d")) exitValue++;
193
194 // Make sure that whitespace doesn't interfere with the removal of the
195 // appropriate tokens. (space-tab-space preceeds -jre-restict-search).
196 if (!doExec("-a -b \t -jre-restrict-search -c -d","-a -b -c -d")) exitValue++;
197
198 // Make sure that the mJRE tokens being stripped, aren't stripped if
199 // they happen to appear as arguments to the main class.
200 if (!doExec("foo -version:1.1+")) exitValue++;
201
202 System.out.println("Completed Arrrghs arguments quoting/matching tests with " + exitValue + " errors");
203 System.exit(exitValue);
204 }
205
206}