8080490: add $EXECV command to Nashorn scripting mode

Tue, 09 Jun 2015 09:27:02 +0200

author
mhaupt
date
Tue, 09 Jun 2015 09:27:02 +0200
changeset 1403
b39a918a34a4
parent 1402
523767716eb3
child 1404
271aceb4b3f0

8080490: add $EXECV command to Nashorn scripting mode
Summary: Additional arguments to the command line can be passed as a single array, or as a sequence of varargs.
Reviewed-by: attila, hannesw

samples/exec.js file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/ScriptObject.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/ScriptingFunctions.java file | annotate | diff | comparison | revisions
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/samples/exec.js	Tue Jun 09 09:27:02 2015 +0200
     1.3 @@ -0,0 +1,48 @@
     1.4 +# exec script requires -scripting mode
     1.5 +
     1.6 +/*
     1.7 + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
     1.8 + *
     1.9 + * Redistribution and use in source and binary forms, with or without
    1.10 + * modification, are permitted provided that the following conditions
    1.11 + * are met:
    1.12 + *
    1.13 + *   - Redistributions of source code must retain the above copyright
    1.14 + *     notice, this list of conditions and the following disclaimer.
    1.15 + *
    1.16 + *   - Redistributions in binary form must reproduce the above copyright
    1.17 + *     notice, this list of conditions and the following disclaimer in the
    1.18 + *     documentation and/or other materials provided with the distribution.
    1.19 + *
    1.20 + *   - Neither the name of Oracle nor the names of its
    1.21 + *     contributors may be used to endorse or promote products derived
    1.22 + *     from this software without specific prior written permission.
    1.23 + *
    1.24 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
    1.25 + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
    1.26 + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    1.27 + * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
    1.28 + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    1.29 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    1.30 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
    1.31 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
    1.32 + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
    1.33 + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    1.34 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    1.35 + */
    1.36 +
    1.37 +// The $EXEC builtin function can be used to run external commands:
    1.38 +$EXEC("ls")
    1.39 +$EXEC("ls -la")
    1.40 +
    1.41 +// It can also be given a string to use as stdin:
    1.42 +$EXEC("cat", "Hello, world!")
    1.43 +
    1.44 +// Additional arguments can be passed after the stdin argument, as an array of
    1.45 +// strings, or a sequence of varargs:
    1.46 +$EXEC("ls", "" /* no stdin */, "-l", "-a")
    1.47 +$EXEC("ls", "" /* no stdin */, ["-l", "-a"])
    1.48 +
    1.49 +// Output of running external commands is returned from $EXEC:
    1.50 +print($EXEC("ls"))
    1.51 +
     2.1 --- a/src/jdk/nashorn/internal/runtime/ScriptObject.java	Mon Jun 08 10:28:04 2015 +0200
     2.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java	Tue Jun 09 09:27:02 2015 +0200
     2.3 @@ -2580,15 +2580,18 @@
     2.4  
     2.5          final int parameterCount = methodType.parameterCount();
     2.6          final int callCount      = callType.parameterCount();
     2.7 +        final int pdiff          = callCount - parameterCount + 1;
     2.8  
     2.9          final boolean isCalleeVarArg = parameterCount > 0 && methodType.parameterType(parameterCount - 1).isArray();
    2.10 -        final boolean isCallerVarArg = callerVarArg != null ? callerVarArg.booleanValue() : callCount > 0 &&
    2.11 +        final boolean isCallerVarArg = callerVarArg != null ? callerVarArg : callCount > 0 &&
    2.12                  callType.parameterType(callCount - 1).isArray();
    2.13  
    2.14 -        if (isCalleeVarArg) {
    2.15 +        // A value of pdiff < 0 means that there are additional normal arguments in the callee that must not be consumed
    2.16 +        // by the vararg collector. No vararg collector is required in that case, and no varargs are passed.
    2.17 +        if (isCalleeVarArg && pdiff >= 0) {
    2.18              return isCallerVarArg ?
    2.19                  methodHandle :
    2.20 -                MH.asCollector(methodHandle, Object[].class, callCount - parameterCount + 1);
    2.21 +                MH.asCollector(methodHandle, Object[].class, pdiff);
    2.22          }
    2.23  
    2.24          if (isCallerVarArg) {
     3.1 --- a/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java	Mon Jun 08 10:28:04 2015 +0200
     3.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java	Tue Jun 09 09:27:02 2015 +0200
     3.3 @@ -41,6 +41,7 @@
     3.4  import java.util.ArrayList;
     3.5  import java.util.List;
     3.6  import java.util.Map;
     3.7 +import jdk.nashorn.internal.objects.NativeArray;
     3.8  
     3.9  /**
    3.10   * Global functions supported only in scripting mode.
    3.11 @@ -54,7 +55,7 @@
    3.12      public static final MethodHandle READFULLY = findOwnMH("readFully",     Object.class, Object.class, Object.class);
    3.13  
    3.14      /** Handle to implementation of {@link ScriptingFunctions#exec} - Nashorn extension */
    3.15 -    public static final MethodHandle EXEC = findOwnMH("exec",     Object.class, Object.class, Object.class, Object.class);
    3.16 +    public static final MethodHandle EXEC = findOwnMH("exec",     Object.class, Object.class, Object.class, Object.class, Object[].class);
    3.17  
    3.18      /** EXEC name - special property used by $EXEC API. */
    3.19      public static final String EXEC_NAME = "$EXEC";
    3.20 @@ -128,17 +129,30 @@
    3.21       * @param self   self reference
    3.22       * @param string string to execute
    3.23       * @param input  input
    3.24 +     * @param argv   additional arguments, to be appended to {@code string}. Additional arguments can be passed as
    3.25 +     *               either one JavaScript array, whose elements will be converted to strings; or as a sequence of
    3.26 +     *               varargs, each of which will be converted to a string.
    3.27       *
    3.28       * @return output string from the request
    3.29 +     *
    3.30       * @throws IOException           if any stream access fails
    3.31       * @throws InterruptedException  if execution is interrupted
    3.32       */
    3.33 -    public static Object exec(final Object self, final Object string, final Object input) throws IOException, InterruptedException {
    3.34 +    public static Object exec(final Object self, final Object string, final Object input, final Object... argv) throws IOException, InterruptedException {
    3.35          // Current global is need to fetch additional inputs and for additional results.
    3.36          final ScriptObject global = Context.getGlobal();
    3.37  
    3.38 +        // Assemble command line, process additional arguments.
    3.39 +        final List<String> cmdLine = tokenizeString(JSType.toString(string));
    3.40 +        final Object[] additionalArgs = argv.length == 1 && argv[0] instanceof NativeArray ?
    3.41 +                ((NativeArray) argv[0]).asObjectArray() :
    3.42 +                argv;
    3.43 +        for (Object arg : additionalArgs) {
    3.44 +            cmdLine.add(JSType.toString(arg));
    3.45 +        }
    3.46 +
    3.47          // Set up initial process.
    3.48 -        final ProcessBuilder processBuilder = new ProcessBuilder(tokenizeString(JSType.toString(string)));
    3.49 +        final ProcessBuilder processBuilder = new ProcessBuilder(cmdLine);
    3.50  
    3.51          // Current ENV property state.
    3.52          final Object env = global.get(ENV_NAME);

mercurial