001: /*
002: * @(#)Win32Process.java 1.30 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026:
027: package java.lang;
028:
029: import java.io.*;
030:
031: class Win32Process extends Process {
032: private long handle = 0;
033: private FileDescriptor stdin_fd;
034: private FileDescriptor stdout_fd;
035: private FileDescriptor stderr_fd;
036: private OutputStream stdin_stream;
037: private InputStream stdout_stream;
038: private InputStream stderr_stream;
039: private int exitcode;
040: private boolean hasExited;
041:
042: Win32Process(String cmd[], String env[]) throws Exception {
043: this (cmd, env, null);
044: }
045:
046: Win32Process(String cmd[], String env[], String path)
047: throws Exception {
048: StringBuffer cmdbuf = new StringBuffer(80);
049: for (int i = 0; i < cmd.length; i++) {
050: if (i > 0) {
051: cmdbuf.append(' ');
052: }
053: String s = cmd[i];
054: if (s.indexOf(' ') >= 0 || s.indexOf('\t') >= 0) {
055: if (s.charAt(0) != '"') {
056: cmdbuf.append('"');
057: cmdbuf.append(s);
058: if (s.endsWith("\\")) {
059: cmdbuf.append("\\");
060: }
061: cmdbuf.append('"');
062: } else if (s.endsWith("\"")) {
063: /* The argument has already been quoted. */
064: cmdbuf.append(s);
065: } else {
066: /* Unmatched quote for the argument. */
067: throw new IllegalArgumentException();
068: }
069: } else {
070: cmdbuf.append(s);
071: }
072: }
073: String cmdstr = cmdbuf.toString();
074:
075: String envstr = null;
076: if (env != null) {
077: StringBuffer envbuf = new StringBuffer(256);
078: for (int i = 0; i < env.length; i++) {
079: envbuf.append(env[i]).append('\0');
080: }
081: envstr = envbuf.toString();
082: }
083:
084: stdin_fd = new FileDescriptor();
085: stdout_fd = new FileDescriptor();
086: stderr_fd = new FileDescriptor();
087:
088: handle = create(cmdstr, envstr, path, stdin_fd, stdout_fd,
089: stderr_fd);
090: java.security.AccessController
091: .doPrivileged(new java.security.PrivilegedAction() {
092: public Object run() {
093: stdin_stream = new BufferedOutputStream(
094: new FileOutputStream(stdin_fd));
095: stdout_stream = new BufferedInputStream(
096: new FileInputStream(stdout_fd));
097: stderr_stream = new FileInputStream(stderr_fd);
098:
099: /*
100: * For each subprocess forked a corresponding reaper thread
101: * is started. That thread is the only thread which waits
102: * for the subprocess to terminate and it doesn't hold any
103: * locks while doing so. This design allows waitFor() and
104: * exitStatus() to be safely executed in parallel (and they
105: * need no native code).
106: */
107:
108: Thread t = new Thread("process reaper") {
109: public void run() {
110: int res = waitFor0();
111: synchronized (Win32Process.this ) {
112: hasExited = true;
113: exitcode = res;
114: Win32Process.this .notifyAll();
115: }
116: }
117: };
118: t.setDaemon(true);
119: t.start();
120:
121: return null;
122: }
123: });
124: }
125:
126: public OutputStream getOutputStream() {
127: return stdin_stream;
128: }
129:
130: public InputStream getInputStream() {
131: return stdout_stream;
132: }
133:
134: public InputStream getErrorStream() {
135: return stderr_stream;
136: }
137:
138: public void finalize() {
139: close();
140: }
141:
142: private native int waitFor0();
143:
144: public native void destroy();
145:
146: public synchronized int waitFor() throws InterruptedException {
147: while (!hasExited) {
148: wait();
149: }
150: return exitcode;
151: }
152:
153: public synchronized int exitValue() {
154: if (!hasExited) {
155: throw new IllegalThreadStateException(
156: "process hasn't exited");
157: }
158: return exitcode;
159: }
160:
161: private native long create(String cmdstr, String envstr,
162: String path, FileDescriptor in_fd, FileDescriptor out_fd,
163: FileDescriptor err_fd);
164:
165: private native void close();
166: }
|