001: /*
002: * @(#)SymbianProcess.java 1.3 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 SymbianProcess 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: SymbianProcess(String cmd[], String env[]) throws Exception {
043: this (cmd, env, null);
044: }
045:
046: SymbianProcess(String cmd[], String env[], String path)
047: throws Exception {
048: StringBuffer cmdbuf = new StringBuffer(80);
049: String exe = "";
050: if (cmd.length > 0) {
051: exe = cmd[0];
052: }
053: for (int i = 1; i < cmd.length; i++) {
054: if (i > 0) {
055: cmdbuf.append(' ');
056: }
057: String s = cmd[i];
058: if (s.indexOf(' ') >= 0 || s.indexOf('\t') >= 0) {
059: if (s.charAt(0) != '"') {
060: cmdbuf.append('"');
061: cmdbuf.append(s);
062: if (s.endsWith("\\")) {
063: cmdbuf.append("\\");
064: }
065: cmdbuf.append('"');
066: } else if (s.endsWith("\"")) {
067: /* The argument has already been quoted. */
068: cmdbuf.append(s);
069: } else {
070: /* Unmatched quote for the argument. */
071: throw new IllegalArgumentException();
072: }
073: } else {
074: cmdbuf.append(s);
075: }
076: }
077: String cmdstr = cmdbuf.toString();
078:
079: String envstr = null;
080: if (env != null) {
081: StringBuffer envbuf = new StringBuffer(256);
082: for (int i = 0; i < env.length; i++) {
083: envbuf.append(env[i]).append('\0');
084: }
085: envstr = envbuf.toString();
086: }
087:
088: stdin_fd = new FileDescriptor();
089: stdout_fd = new FileDescriptor();
090: stderr_fd = new FileDescriptor();
091:
092: handle = create(exe, cmdstr, envstr, path, stdin_fd, stdout_fd,
093: stderr_fd);
094: java.security.AccessController
095: .doPrivileged(new java.security.PrivilegedAction() {
096: public Object run() {
097: stdin_stream = new BufferedOutputStream(
098: new FileOutputStream(stdin_fd));
099: stdout_stream = new BufferedInputStream(
100: new FileInputStream(stdout_fd));
101: stderr_stream = new FileInputStream(stderr_fd);
102:
103: /*
104: * For each subprocess forked a corresponding reaper thread
105: * is started. That thread is the only thread which waits
106: * for the subprocess to terminate and it doesn't hold any
107: * locks while doing so. This design allows waitFor() and
108: * exitStatus() to be safely executed in parallel (and they
109: * need no native code).
110: */
111:
112: Thread t = new Thread("process reaper") {
113: public void run() {
114: int res = waitFor0();
115: synchronized (SymbianProcess.this ) {
116: hasExited = true;
117: exitcode = res;
118: SymbianProcess.this .notifyAll();
119: }
120: }
121: };
122: t.setDaemon(true);
123: t.start();
124:
125: return null;
126: }
127: });
128: }
129:
130: public OutputStream getOutputStream() {
131: return stdin_stream;
132: }
133:
134: public InputStream getInputStream() {
135: return stdout_stream;
136: }
137:
138: public InputStream getErrorStream() {
139: return stderr_stream;
140: }
141:
142: public void finalize() {
143: close();
144: }
145:
146: private native int waitFor0();
147:
148: public native void destroy();
149:
150: public synchronized int waitFor() throws InterruptedException {
151: while (!hasExited) {
152: wait();
153: }
154: return exitcode;
155: }
156:
157: public synchronized int exitValue() {
158: if (!hasExited) {
159: throw new IllegalThreadStateException(
160: "process hasn't exited");
161: }
162: return exitcode;
163: }
164:
165: private native long create(String exe, String args, String envstr,
166: String path, FileDescriptor in_fd, FileDescriptor out_fd,
167: FileDescriptor err_fd);
168:
169: private native void close();
170: }
|