Home | History | Annotate | Download | only in support
      1 /*
      2  * Licensed to the Apache Software Foundation (ASF) under one or more
      3  * contributor license agreements.  See the NOTICE file distributed with
      4  * this work for additional information regarding copyright ownership.
      5  * The ASF licenses this file to You under the Apache License, Version 2.0
      6  * (the "License"); you may not use this file except in compliance with
      7  * the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 
     18 package tests.support;
     19 
     20 import java.io.ByteArrayOutputStream;
     21 import java.io.File;
     22 import java.io.IOException;
     23 import java.io.InputStream;
     24 import java.io.PrintStream;
     25 import java.util.ArrayList;
     26 import java.util.List;
     27 import java.util.StringTokenizer;
     28 
     29 import junit.framework.TestCase;
     30 
     31 public class Support_Exec extends TestCase {
     32 
     33     /**
     34      * Exec java returns the exitCode, and stdOut and stdErr as strings
     35      */
     36     public static Object[] runJava(List<String> args, String[] envp,
     37             boolean displayOutput)
     38             throws IOException, InterruptedException {
     39         String executable = System.getProperty("java.home");
     40         if (!executable.endsWith(File.separator)) {
     41             executable += File.separator;
     42         }
     43         executable += "bin" + File.separator + "java";
     44 
     45         // parse hy.test.vmargs if was given
     46         String testVMArgs = System.getProperty("hy.test.vmargs");
     47         if (testVMArgs != null) {
     48             StringTokenizer st = new StringTokenizer(testVMArgs, " ");
     49             int i = 0; // add at the beginning but maintain order
     50             while (st.hasMoreTokens()) {
     51                 args.add(i++, st.nextToken());
     52             }
     53         }
     54 
     55         return run(executable, args, envp, displayOutput);
     56     }
     57 
     58     /**
     59      * Exec command returns the exitCode, and stdOut and stdErr as strings
     60      */
     61     public static Object[] run(String command, List<String> args, String[] envp,
     62             boolean displayOutput)
     63             throws IOException, InterruptedException {
     64         Object[] arr = exec(command, args, envp, displayOutput);
     65 
     66         Process proc = (Process) arr[0];
     67         StringBuilder output = new StringBuilder();
     68         InputStream in = proc.getInputStream();
     69         int result;
     70         byte[] bytes = new byte[1024];
     71 
     72         while ((result = in.read(bytes)) != -1) {
     73             output.append(new String(bytes, 0, result));
     74             if (displayOutput) {
     75                 System.out.write(bytes, 0, result);
     76             }
     77         }
     78 
     79         in.close();
     80         proc.waitFor();
     81         int exitCode = proc.exitValue();
     82         proc.destroy();
     83         return new Object[] {
     84                 Integer.valueOf(exitCode),
     85                 output.toString(),
     86                 ((StringBuilder) arr[1]).toString()
     87         };
     88     }
     89 
     90     /**
     91      * This function returns the output of the process as a string
     92      */
     93     public static String execJava(String[] args, String[] classpath,
     94             boolean displayOutput)
     95             throws IOException, InterruptedException {
     96         Object[] arr =
     97                 execJavaCommon(args, classpath, null, displayOutput, true);
     98 
     99         return getProcessOutput(arr, displayOutput, true);
    100     }
    101 
    102     /**
    103      * This function returns the output of the process as a string
    104      */
    105     public static String execJava(String[] args, String[] classpath,
    106             String[] envp, boolean displayOutput)
    107             throws IOException, InterruptedException {
    108         Object[] arr =
    109                 execJavaCommon(args, classpath, envp, displayOutput, false);
    110 
    111         return getProcessOutput(arr, displayOutput, true);
    112     }
    113 
    114     private static String getProcessOutput(Object[] arr, boolean displayOutput,
    115             boolean checkStderr)
    116             throws IOException, InterruptedException {
    117         Process proc = (Process) arr[0];
    118         StringBuilder output = new StringBuilder();
    119         InputStream in = proc.getInputStream();
    120         int result;
    121         byte[] bytes = new byte[1024];
    122 
    123         while ((result = in.read(bytes)) != -1) {
    124             output.append(new String(bytes, 0, result));
    125             if (displayOutput) {
    126                 System.out.write(bytes, 0, result);
    127             }
    128         }
    129 
    130         in.close();
    131         proc.waitFor();
    132         if (checkStderr) {
    133             checkStderr(arr);
    134         }
    135         proc.destroy();
    136 
    137         return output.toString();
    138     }
    139 
    140     public static void checkStderr(Object[] execArgs) {
    141         StringBuilder errBuf = (StringBuilder) execArgs[1];
    142 
    143         synchronized (errBuf) {
    144             if (errBuf.length() > 0) {
    145                 fail(errBuf.toString());
    146             }
    147         }
    148     }
    149 
    150     public static Object[] execJava2(String[] args, String[] classpath,
    151             boolean displayOutput)
    152             throws IOException, InterruptedException {
    153         return execJavaCommon(args, classpath, null, displayOutput, true);
    154     }
    155 
    156     private static Object[] execJavaCommon(String[] args, String[] classpath,
    157             String[] envp,
    158             boolean displayOutput,
    159             boolean appendToSystemClassPath)
    160             throws IOException, InterruptedException {
    161         // this function returns the resulting process from the exec
    162         ArrayList<String> execArgs = null;
    163         StringBuilder classPathString = new StringBuilder();
    164         StringBuilder command;
    165 
    166         execArgs = new ArrayList<String>(3 + args.length);
    167 
    168         // construct the name of executable file
    169         String executable = System.getProperty("java.home");
    170         if (!executable.endsWith(File.separator)) {
    171             executable += File.separator;
    172         }
    173         executable += "bin" + File.separator + "java";
    174 
    175         // add classpath string
    176         if (classpath != null) {
    177             for (String element : classpath) {
    178                 classPathString.append(File.pathSeparator);
    179                 classPathString.append(element);
    180             }
    181         }
    182         if (appendToSystemClassPath) {
    183             execArgs.add("-cp");
    184             execArgs.add(System.getProperty("java.class.path") +
    185                     classPathString);
    186         } else {
    187             if (classpath != null) {
    188                 execArgs.add("-cp");
    189                 execArgs.add(classPathString.toString());
    190             }
    191         }
    192 
    193         // parse hy.test.vmargs if was given
    194         String testVMArgs = System.getProperty("hy.test.vmargs");
    195         if (testVMArgs != null) {
    196             StringTokenizer st = new StringTokenizer(testVMArgs, " ");
    197 
    198             while (st.hasMoreTokens()) {
    199                 execArgs.add(st.nextToken());
    200             }
    201         }
    202 
    203         // add custom args given as parameter
    204         for (String arg : args) {
    205             execArgs.add(arg);
    206         }
    207         return exec(executable, execArgs, envp, displayOutput);
    208     }
    209 
    210     private static Object[] exec(String command, List<String> args,
    211             String[] envp,
    212             boolean displayOutput)
    213             throws IOException, InterruptedException {
    214         // this function returns the resulting process from the exec
    215         args.add(0, command);
    216 
    217         if (displayOutput) {
    218             StringBuilder commandLine;
    219             // construct command line string and print it to stdout
    220             commandLine = new StringBuilder(args.get(0));
    221             for (int i = 1; i < args.size(); i++) {
    222                 commandLine.append(" ");
    223                 commandLine.append(args.get(i));
    224             }
    225             System.out.println("Exec: " + commandLine.toString());
    226             System.out.println();
    227         }
    228 
    229         // execute java process
    230         final Process proc =
    231                 Runtime.getRuntime().exec(args.toArray(new String[args.size()]),
    232                         envp);
    233 
    234         final StringBuilder errBuf = new StringBuilder();
    235         Thread errThread = new Thread(new Runnable() {
    236             public void run() {
    237                 synchronized (errBuf) {
    238                     InputStream err;
    239                     int result;
    240                     byte[] bytes = new byte[1024];
    241 
    242                     synchronized (proc) {
    243                         proc.notifyAll();
    244                     }
    245 
    246                     err = proc.getErrorStream();
    247                     try {
    248                         while ((result = err.read(bytes)) != -1) {
    249                             System.err.write(bytes, 0, result);
    250                             errBuf.append(new String(bytes));
    251                         }
    252                         err.close();
    253                     } catch (IOException e) {
    254                         ByteArrayOutputStream out =
    255                                 new ByteArrayOutputStream();
    256                         PrintStream printer = new PrintStream(out);
    257 
    258                         e.printStackTrace();
    259                         e.printStackTrace(printer);
    260                         printer.close();
    261                         errBuf.append(new String(out.toByteArray()));
    262                     }
    263                 }
    264             }
    265         });
    266 
    267         synchronized (proc) {
    268             errThread.start();
    269             // wait for errThread to start
    270             int count = 0;
    271             boolean isFinished = false;
    272             while (!isFinished) {
    273                 try {
    274                     proc.wait();
    275                     isFinished = true;
    276                 } catch (InterruptedException e) {
    277                     if (++count == 2) {
    278                         throw e;
    279                     }
    280                 }
    281             }
    282             if (count > 0) {
    283                 Thread.currentThread().interrupt();
    284             }
    285         }
    286         return new Object[] { proc, errBuf };
    287     }
    288 }
    289