Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(103)

Unified Diff: runtime/bin/process_impl.dart

Issue 9863015: This is a request for comments. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Minor indentation fixes Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: runtime/bin/process_impl.dart
diff --git a/runtime/bin/process_impl.dart b/runtime/bin/process_impl.dart
index b62491534bad2b5e9c417db3b532b833dcca9e3a..86e577979d97105bde3f004a99462837e2a9f69a 100644
--- a/runtime/bin/process_impl.dart
+++ b/runtime/bin/process_impl.dart
@@ -8,25 +8,53 @@ class _ProcessStartStatus {
}
+// Abstract factory class capable of producing interactive and
+// non-interactive processes.
class _Process implements Process {
- _Process.start(String path,
- List<String> arguments,
- [String workingDirectory]) {
+ _Process();
+
+ factory _Process.start(String path,
+ List<String> arguments,
+ [ProcessOptions options]) {
+ return new _InteractiveProcess.start(path, arguments, options);
+ }
+
+ factory _Process.run(String path,
+ List<String> arguments,
+ ProcessOptions options,
+ void callback(int exitCode,
+ String stdout,
+ String stderr)) {
+ return new _NonInteractiveProcess.start(path,
+ arguments,
+ options,
+ callback);
+ }
+}
+
+
+// _InteractiveProcess is the actual implementation of all processes
+// started from Dart code.
+class _InteractiveProcess extends _Process {
+
+ _InteractiveProcess.start(String path,
+ List<String> arguments,
+ ProcessOptions options) {
if (path is !String) {
- throw new ProcessException("Path is not a String: $path");
+ throw new IllegalArgumentException("Path is not a String: $path");
}
_path = path;
if (arguments is !List) {
- throw new ProcessException("Arguments is not a List: $arguments");
+ throw new IllegalArgumentException("Arguments is not a List: $arguments");
}
int len = arguments.length;
_arguments = new ObjectArray<String>(len);
for (int i = 0; i < len; i++) {
var arg = arguments[i];
if (arg is !String) {
- throw new ProcessException("Non-string argument: $arg");
+ throw new IllegalArgumentException("Non-string argument: $arg");
}
_arguments[i] = arguments[i];
if (new Platform().operatingSystem() == 'windows') {
@@ -34,11 +62,13 @@ class _Process implements Process {
}
}
- if (workingDirectory is !String && workingDirectory !== null) {
- throw new ProcessException(
- "WorkingDirectory is not a String: $workingDirectory");
+ if (options !== null && options.workingDirectory !== null) {
+ _workingDirectory = options.workingDirectory;
+ if (_workingDirectory is !String) {
+ throw new IllegalArgumentException(
+ "WorkingDirectory is not a String: $_workingDirectory");
+ }
}
- _workingDirectory = workingDirectory;
_in = new _Socket._internalReadOnly(); // stdout coming from process.
_out = new _Socket._internalWriteOnly(); // stdin going to process.
@@ -259,3 +289,119 @@ class _Process implements Process {
Function _onError;
Function _onStart;
}
+
+
+// _NonInteractiveProcess is a wrapper around an interactive process
+// that restricts the interface to disallow access to the streams and
+// buffers output so it can be delivered to the callback when the
+// process exits.
+class _NonInteractiveProcess extends _Process {
+
+ _NonInteractiveProcess.start(String path,
+ List<String> arguments,
+ ProcessOptions options,
+ Function this._callback) {
+ _process = new _InteractiveProcess.start(path, arguments, options);
+
+ // Setup process exit handling.
+ _process.onExit = (exitCode) {
+ _exitCode = exitCode;
+ _checkDone();
+ };
+
+ // Extract output encoding options.
+ var stdoutEncoding = Encoding.UTF_8;
+ var stderrEncoding = Encoding.UTF_8;
+ if (options !== null) {
+ if (options.stdoutEncoding !== null) {
+ stdoutEncoding = options.stdoutEncoding;
+ if (stdoutEncoding is !Encoding) {
Søren Gjesse 2012/04/12 15:02:21 Maybe we should get rid of this type check and mov
Mads Ager (google) 2012/04/13 08:49:39 It will throw an exception through the StringInput
+ throw new IllegalArgumentException(
+ 'stdoutEncoding option is not an encoding: $stdoutEncoding');
+ }
+ }
+ if (options.stderrEncoding !== null) {
+ stderrEncoding = options.stderrEncoding;
+ if (stderrEncoding is !Encoding) {
Søren Gjesse 2012/04/12 15:02:21 Ditto.
+ throw new IllegalArgumentException(
+ 'stderrEncoding option is not an encoding: $stderrEncoding');
+ }
+ }
+ }
+
+ // Setup stdout handling.
+ _stdoutBuffer = new StringBuffer();
+ var stdoutStream = new StringInputStream(_process.stdout, stdoutEncoding);
+ stdoutStream.onData = () {
+ var data = stdoutStream.read();
+ if (data != null) _stdoutBuffer.add(data);
+ };
+ stdoutStream.onClosed = () {
+ _stdoutClosed = true;
+ _checkDone();
+ };
+
+ // Setup stderr handling.
+ _stderrBuffer = new StringBuffer();
+ var stderrStream = new StringInputStream(_process.stderr, stderrEncoding);
+ stderrStream.onData = () {
+ var data = stderrStream.read();
+ if (data != null) _stderrBuffer.add(data);
+ };
+ stderrStream.onClosed = () {
+ _stderrClosed = true;
+ _checkDone();
+ };
+ }
+
+ void _checkDone() {
+ if (_exitCode != null && _stderrClosed && _stdoutClosed) {
+ _callback(_exitCode, _stdoutBuffer.toString(), _stderrBuffer.toString());
+ }
+ }
+
+ InputStream get stdout() {
+ throw new UnsupportedOperationException(
+ 'Cannot get stdout stream for process started with '
+ 'the run constructor. The entire stdout '
+ 'will be supplied in the callback on completion.');
+ }
+
+ InputStream get stderr() {
+ throw new UnsupportedOperationException(
+ 'Cannot get stderr stream for process started with '
+ 'the run constructor. The entire stderr '
+ 'will be supplied in the callback on completion.');
+ }
+
+ OutputStream get stdin() {
+ throw new UnsupportedOperationException(
+ 'Cannot communicate via stdin with process started with '
+ 'the run constructor');
+ }
+
+ void set onStart(void callback()) => _process.onStart = callback;
+
+ void set onExit(void callback(int exitCode)) {
+ throw new UnsupportedOperationException(
+ 'Cannot set exit handler on process started with '
+ 'the run constructor. The exit code will '
+ 'be supplied in the callback on completion.');
+ }
+
+ void set onError(void callback(ProcessException error)) {
+ _process.onError = callback;
+ }
+
+ void kill() => _process.kill();
+
+ void close() => _process.close();
+
+ Process _process;
+ Function _callback;
+ StringBuffer _stdoutBuffer;
+ StringBuffer _stderrBuffer;
+ int _exitCode;
+ bool _stdoutClosed = false;
+ bool _stderrClosed = false;
+}

Powered by Google App Engine
This is Rietveld 408576698