< prev index next >

src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/Shell.java

Print this page
rev 1525 : 8143642: Nashorn shebang argument handling is broken

*** 34,47 **** import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintStream; import java.io.PrintWriter; ! import java.util.Iterator; ! import java.util.List; ! import java.util.Locale; ! import java.util.ResourceBundle; import jdk.nashorn.api.scripting.NashornException; import jdk.nashorn.internal.codegen.Compiler; import jdk.nashorn.internal.codegen.Compiler.CompilationPhases; import jdk.nashorn.internal.ir.Expression; import jdk.nashorn.internal.ir.FunctionNode; --- 34,49 ---- import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintStream; import java.io.PrintWriter; ! import java.nio.file.Files; ! import java.nio.file.Path; ! import java.nio.file.Paths; ! import java.util.*; ! import java.util.stream.Collectors; ! import jdk.nashorn.api.scripting.NashornException; import jdk.nashorn.internal.codegen.Compiler; import jdk.nashorn.internal.codegen.Compiler.CompilationPhases; import jdk.nashorn.internal.ir.Expression; import jdk.nashorn.internal.ir.FunctionNode;
*** 199,209 **** final Options options = new Options("nashorn", werr); // parse options if (args != null) { try { ! options.process(args); } catch (final IllegalArgumentException e) { werr.println(bundle.getString("shell.usage")); options.displayHelp(e); return null; } --- 201,212 ---- final Options options = new Options("nashorn", werr); // parse options if (args != null) { try { ! final String[] prepArgs = preprocessArgs(args); ! options.process(prepArgs); } catch (final IllegalArgumentException e) { werr.println(bundle.getString("shell.usage")); options.displayHelp(e); return null; }
*** 230,239 **** --- 233,303 ---- return new Context(options, errors, wout, werr, Thread.currentThread().getContextClassLoader()); } /** + * Preprocess the command line arguments passed in by the shell. This checks, for each of the arguments, whether it + * can be a file name, and if so, whether the file exists. If the file exists and begins with a shebang line, and + * the arguments on that line are a prefix of {@code args} with the file removed, it is assumed that a script file + * being executed via shebang was found, and it is moved to the appropriate position in the argument list. The first + * such match is used. + * <p> + * This method canonicalizes the command line arguments to the form {@code <options> <scripts> -- <arguments>}, + * where the last of the {@code scripts} is the one being run in shebang fashion. + * + * @param args the command line arguments as passed into Nashorn. + * @return a properly ordered argument list + */ + private static String[] preprocessArgs(final String[] args) { + final List<String> largs = new ArrayList<>(); + Collections.addAll(largs, args); + final List<String> pa = new ArrayList<>(); + String scriptFile = null; + boolean found = false; + for (int i = 0; i < args.length; ++i) { + final String a = args[i]; + final Path p = Paths.get(a); + if (!found && (!a.startsWith("-") || a.length() == 1) && Files.exists(p)) { + String l = ""; + try (final BufferedReader r = Files.newBufferedReader(p)) { + l = r.readLine(); + } catch (IOException ioe) { + // ignore + } + if (l.startsWith("#!")) { + List<String> shebangArgs = Arrays.asList(l.split(" ")); + shebangArgs = shebangArgs.subList(1, shebangArgs.size()); // remove #! part + final int ssize = shebangArgs.size(); + final List<String> filteredArgs = largs.stream().filter(x -> !x.equals(a)).collect(Collectors.toList()); + if (filteredArgs.size() >= ssize && shebangArgs.equals(filteredArgs.subList(0, ssize))) { + scriptFile = a; + found = true; + continue; + } + } + } + pa.add(a); + } + if (scriptFile != null) { + // Insert the found script file name either before a -- argument, or at the end of the options list, before + // any other arguments, with an extra --. + int argidx = pa.indexOf("--"); + if (argidx == -1) { + for (String s : pa) { + ++argidx; + if (s.charAt(0) != '-') { + pa.add(argidx, "--"); + break; + } + } + } + pa.add(argidx, scriptFile); + } + return pa.stream().toArray(String[]::new); + } + + /** * Compiles the given script files in the command line * This is called only when using the --compile-only flag * * @param context the nashorn context * @param global the global scope
< prev index next >