blob: 9db29772571d90d6d27db22a7ff6868573ba8970 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
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
26package java.lang;
27
28import java.io.*;
29
30/* This class is for the exclusive use of ProcessBuilder.start() to
31 * create new processes.
32 *
33 * @author Martin Buchholz
34 * @since 1.5
35 */
36
37final class ProcessImpl extends Process {
38
39 // System-dependent portion of ProcessBuilder.start()
40 static Process start(String cmdarray[],
41 java.util.Map<String,String> environment,
42 String dir,
43 boolean redirectErrorStream)
44 throws IOException
45 {
46 String envblock = ProcessEnvironment.toEnvironmentBlock(environment);
47 return new ProcessImpl(cmdarray, envblock, dir, redirectErrorStream);
48 }
49
50 private long handle = 0;
51 private FileDescriptor stdin_fd;
52 private FileDescriptor stdout_fd;
53 private FileDescriptor stderr_fd;
54 private OutputStream stdin_stream;
55 private InputStream stdout_stream;
56 private InputStream stderr_stream;
57
58 private ProcessImpl(String cmd[],
59 String envblock,
60 String path,
61 boolean redirectErrorStream)
62 throws IOException
63 {
64 // Win32 CreateProcess requires cmd[0] to be normalized
65 cmd[0] = new File(cmd[0]).getPath();
66
67 StringBuilder cmdbuf = new StringBuilder(80);
68 for (int i = 0; i < cmd.length; i++) {
69 if (i > 0) {
70 cmdbuf.append(' ');
71 }
72 String s = cmd[i];
73 if (s.indexOf(' ') >= 0 || s.indexOf('\t') >= 0) {
74 if (s.charAt(0) != '"') {
75 cmdbuf.append('"');
76 cmdbuf.append(s);
77 if (s.endsWith("\\")) {
78 cmdbuf.append("\\");
79 }
80 cmdbuf.append('"');
81 } else if (s.endsWith("\"")) {
82 /* The argument has already been quoted. */
83 cmdbuf.append(s);
84 } else {
85 /* Unmatched quote for the argument. */
86 throw new IllegalArgumentException();
87 }
88 } else {
89 cmdbuf.append(s);
90 }
91 }
92 String cmdstr = cmdbuf.toString();
93
94 stdin_fd = new FileDescriptor();
95 stdout_fd = new FileDescriptor();
96 stderr_fd = new FileDescriptor();
97
98 handle = create(cmdstr, envblock, path, redirectErrorStream,
99 stdin_fd, stdout_fd, stderr_fd);
100
101 java.security.AccessController.doPrivileged(
102 new java.security.PrivilegedAction() {
103 public Object run() {
104 stdin_stream =
105 new BufferedOutputStream(new FileOutputStream(stdin_fd));
106 stdout_stream =
107 new BufferedInputStream(new FileInputStream(stdout_fd));
108 stderr_stream =
109 new FileInputStream(stderr_fd);
110 return null;
111 }
112 });
113 }
114
115 public OutputStream getOutputStream() {
116 return stdin_stream;
117 }
118
119 public InputStream getInputStream() {
120 return stdout_stream;
121 }
122
123 public InputStream getErrorStream() {
124 return stderr_stream;
125 }
126
127 public void finalize() {
128 closeHandle(handle);
129 }
130
131 private static final int STILL_ACTIVE = getStillActive();
132 private static native int getStillActive();
133
134 public int exitValue() {
135 int exitCode = getExitCodeProcess(handle);
136 if (exitCode == STILL_ACTIVE)
137 throw new IllegalThreadStateException("process has not exited");
138 return exitCode;
139 }
140 private static native int getExitCodeProcess(long handle);
141
142 public int waitFor() throws InterruptedException {
143 waitForInterruptibly(handle);
144 if (Thread.interrupted())
145 throw new InterruptedException();
146 return exitValue();
147 }
148 private static native void waitForInterruptibly(long handle);
149
150 public void destroy() { terminateProcess(handle); }
151 private static native void terminateProcess(long handle);
152
153 private static native long create(String cmdstr,
154 String envblock,
155 String dir,
156 boolean redirectErrorStream,
157 FileDescriptor in_fd,
158 FileDescriptor out_fd,
159 FileDescriptor err_fd)
160 throws IOException;
161
162 private static native boolean closeHandle(long handle);
163}