Save This Page
Home » openjdk-7 » java » lang » [javadoc | source]
    1   /*
    2    * Copyright 1995-2007 Sun Microsystems, Inc.  All Rights Reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   
   26   package java.lang;
   27   
   28   import java.io.IOException;
   29   import java.io.File;
   30   import java.io.InputStream;
   31   import java.io.OutputStream;
   32   import java.io.FileInputStream;
   33   import java.io.FileOutputStream;
   34   import java.io.FileDescriptor;
   35   import java.io.BufferedInputStream;
   36   import java.io.BufferedOutputStream;
   37   import java.lang.ProcessBuilder.Redirect;
   38   
   39   /* This class is for the exclusive use of ProcessBuilder.start() to
   40    * create new processes.
   41    *
   42    * @author Martin Buchholz
   43    * @since   1.5
   44    */
   45   
   46   final class ProcessImpl extends Process {
   47       private static final sun.misc.JavaIOFileDescriptorAccess fdAccess
   48           = sun.misc.SharedSecrets.getJavaIOFileDescriptorAccess();
   49   
   50       // System-dependent portion of ProcessBuilder.start()
   51       static Process start(String cmdarray[],
   52                            java.util.Map<String,String> environment,
   53                            String dir,
   54                            ProcessBuilder.Redirect[] redirects,
   55                            boolean redirectErrorStream)
   56           throws IOException
   57       {
   58           String envblock = ProcessEnvironment.toEnvironmentBlock(environment);
   59   
   60           FileInputStream  f0 = null;
   61           FileOutputStream f1 = null;
   62           FileOutputStream f2 = null;
   63   
   64           try {
   65               long[] stdHandles;
   66               if (redirects == null) {
   67                   stdHandles = new long[] { -1L, -1L, -1L };
   68               } else {
   69                   stdHandles = new long[3];
   70   
   71                   if (redirects[0] == Redirect.PIPE)
   72                       stdHandles[0] = -1L;
   73                   else if (redirects[0] == Redirect.INHERIT)
   74                       stdHandles[0] = fdAccess.getHandle(FileDescriptor.in);
   75                   else {
   76                       f0 = new FileInputStream(redirects[0].file());
   77                       stdHandles[0] = fdAccess.getHandle(f0.getFD());
   78                   }
   79   
   80                   if (redirects[1] == Redirect.PIPE)
   81                       stdHandles[1] = -1L;
   82                   else if (redirects[1] == Redirect.INHERIT)
   83                       stdHandles[1] = fdAccess.getHandle(FileDescriptor.out);
   84                   else {
   85                       f1 = redirects[1].toFileOutputStream();
   86                       stdHandles[1] = fdAccess.getHandle(f1.getFD());
   87                   }
   88   
   89                   if (redirects[2] == Redirect.PIPE)
   90                       stdHandles[2] = -1L;
   91                   else if (redirects[2] == Redirect.INHERIT)
   92                       stdHandles[2] = fdAccess.getHandle(FileDescriptor.err);
   93                   else {
   94                       f2 = redirects[2].toFileOutputStream();
   95                       stdHandles[2] = fdAccess.getHandle(f2.getFD());
   96                   }
   97               }
   98   
   99               return new ProcessImpl(cmdarray, envblock, dir,
  100                                      stdHandles, redirectErrorStream);
  101           } finally {
  102               // In theory, close() can throw IOException
  103               // (although it is rather unlikely to happen here)
  104               try { if (f0 != null) f0.close(); }
  105               finally {
  106                   try { if (f1 != null) f1.close(); }
  107                   finally { if (f2 != null) f2.close(); }
  108               }
  109           }
  110   
  111       }
  112   
  113       private long handle = 0;
  114       private OutputStream stdin_stream;
  115       private InputStream stdout_stream;
  116       private InputStream stderr_stream;
  117   
  118       private ProcessImpl(final String cmd[],
  119                           final String envblock,
  120                           final String path,
  121                           final long[] stdHandles,
  122                           final boolean redirectErrorStream)
  123           throws IOException
  124       {
  125           // Win32 CreateProcess requires cmd[0] to be normalized
  126           cmd[0] = new File(cmd[0]).getPath();
  127   
  128           StringBuilder cmdbuf = new StringBuilder(80);
  129           for (int i = 0; i < cmd.length; i++) {
  130               if (i > 0) {
  131                   cmdbuf.append(' ');
  132               }
  133               String s = cmd[i];
  134               if (s.indexOf(' ') >= 0 || s.indexOf('\t') >= 0) {
  135                   if (s.charAt(0) != '"') {
  136                       cmdbuf.append('"');
  137                       cmdbuf.append(s);
  138                       if (s.endsWith("\\")) {
  139                           cmdbuf.append("\\");
  140                       }
  141                       cmdbuf.append('"');
  142                   } else if (s.endsWith("\"")) {
  143                       /* The argument has already been quoted. */
  144                       cmdbuf.append(s);
  145                   } else {
  146                       /* Unmatched quote for the argument. */
  147                       throw new IllegalArgumentException();
  148                   }
  149               } else {
  150                   cmdbuf.append(s);
  151               }
  152           }
  153           String cmdstr = cmdbuf.toString();
  154   
  155           handle = create(cmdstr, envblock, path,
  156                           stdHandles, redirectErrorStream);
  157   
  158           java.security.AccessController.doPrivileged(
  159           new java.security.PrivilegedAction<Void>() {
  160           public Void run() {
  161               if (stdHandles[0] == -1L)
  162                   stdin_stream = new ProcessBuilder.NullOutputStream();
  163               else {
  164                   FileDescriptor stdin_fd = new FileDescriptor();
  165                   fdAccess.setHandle(stdin_fd, stdHandles[0]);
  166                   stdin_stream = new BufferedOutputStream(
  167                       new FileOutputStream(stdin_fd));
  168               }
  169   
  170               if (stdHandles[1] == -1L)
  171                   stdout_stream = new ProcessBuilder.NullInputStream();
  172               else {
  173                   FileDescriptor stdout_fd = new FileDescriptor();
  174                   fdAccess.setHandle(stdout_fd, stdHandles[1]);
  175                   stdout_stream = new BufferedInputStream(
  176                       new FileInputStream(stdout_fd));
  177               }
  178   
  179               if (stdHandles[2] == -1L)
  180                   stderr_stream = new ProcessBuilder.NullInputStream();
  181               else {
  182                   FileDescriptor stderr_fd = new FileDescriptor();
  183                   fdAccess.setHandle(stderr_fd, stdHandles[2]);
  184                   stderr_stream = new FileInputStream(stderr_fd);
  185               }
  186   
  187               return null; }});
  188       }
  189   
  190       public OutputStream getOutputStream() {
  191           return stdin_stream;
  192       }
  193   
  194       public InputStream getInputStream() {
  195           return stdout_stream;
  196       }
  197   
  198       public InputStream getErrorStream() {
  199           return stderr_stream;
  200       }
  201   
  202       public void finalize() {
  203           closeHandle(handle);
  204       }
  205   
  206       private static final int STILL_ACTIVE = getStillActive();
  207       private static native int getStillActive();
  208   
  209       public int exitValue() {
  210           int exitCode = getExitCodeProcess(handle);
  211           if (exitCode == STILL_ACTIVE)
  212               throw new IllegalThreadStateException("process has not exited");
  213           return exitCode;
  214       }
  215       private static native int getExitCodeProcess(long handle);
  216   
  217       public int waitFor() throws InterruptedException {
  218           waitForInterruptibly(handle);
  219           if (Thread.interrupted())
  220               throw new InterruptedException();
  221           return exitValue();
  222       }
  223       private static native void waitForInterruptibly(long handle);
  224   
  225       public void destroy() { terminateProcess(handle); }
  226       private static native void terminateProcess(long handle);
  227   
  228       /**
  229        * Create a process using the win32 function CreateProcess.
  230        *
  231        * @param cmdstr the Windows commandline
  232        * @param envblock NUL-separated, double-NUL-terminated list of
  233        *        environment strings in VAR=VALUE form
  234        * @param dir the working directory of the process, or null if
  235        *        inheriting the current directory from the parent process
  236        * @param stdHandles array of windows HANDLEs.  Indexes 0, 1, and
  237        *        2 correspond to standard input, standard output and
  238        *        standard error, respectively.  On input, a value of -1
  239        *        means to create a pipe to connect child and parent
  240        *        processes.  On output, a value which is not -1 is the
  241        *        parent pipe handle corresponding to the pipe which has
  242        *        been created.  An element of this array is -1 on input
  243        *        if and only if it is <em>not</em> -1 on output.
  244        * @param redirectErrorStream redirectErrorStream attribute
  245        * @return the native subprocess HANDLE returned by CreateProcess
  246        */
  247       private static native long create(String cmdstr,
  248                                         String envblock,
  249                                         String dir,
  250                                         long[] stdHandles,
  251                                         boolean redirectErrorStream)
  252           throws IOException;
  253   
  254       private static native boolean closeHandle(long handle);
  255   }

Save This Page
Home » openjdk-7 » java » lang » [javadoc | source]