1 jls.loader.provide('jls.lang.Process');
  2 
  3 jls.lang.Process = jls.lang.Class.create( /** @lends jls.lang.Process.prototype */
  4 {
  5     /**
  6      * Creates a process with the specified command and arguments with the specified environment and working directory.
  7      * 
  8      * @param {Array} cmdArray Array of strings specifying the command-line arguments. The first argument is the name of the executable file.
  9      * @param {Array} envp Array of key-values specifying the environment strings. If undefined, the new process inherits the environment of the parent process.
 10      * @param {jls.io.File} dir The working directory of the subprocess, or undefined if the subprocess should inherit the working directory of the current process.
 11      * @constructs
 12      * @class The class Process provides methods for performing input from the process,
 13      * performing output to the process, waiting for the process to complete,
 14      * checking the exit status of the process, and destroying (killing) the process.
 15      */
 16     initialize : function(cmdArray, envp, processAttr) {
 17         var cmd = (typeof cmdArray == 'string') ? [cmdArray] : cmdArray;
 18         this._no = new _native.core.Process(cmd[0], cmd, envp, processAttr);
 19         this._exitValue = jls.lang.Process.STILL_ACTIVE;
 20         this._thread = null;
 21         this._onExitCBs = [];
 22     },
 23     /**
 24      * Kills this process.
 25      */
 26     destroy : function() {
 27     	if (this._no == null) {
 28             throw new jls.lang.Exception('The process is no more reachable');
 29     	}
 30         this._no.kill();
 31         this._exitValue = jls.lang.Process.DESTROYED;
 32         this._no = null;
 33     },
 34     /**
 35      * Detachs this process.
 36      */
 37     detach : function() {
 38     	if (this._no == null) {
 39             throw new jls.lang.Exception('The process is no more reachable');
 40     	}
 41         this._no.detach();
 42         this._exitValue = jls.lang.Process.DETACHED;
 43         this._no = null;
 44     },
 45     /**
 46      * Waits for this process to terminate and return the exit value.
 47      * @returns {Number} This process exit value.
 48      */
 49     waitFor : function() {
 50     	if (this._no == null) {
 51             throw new jls.lang.Exception('The process is no more reachable');
 52     	}
 53     	if (this._thread == null) {
 54             this._exitValue = this._no.wait();
 55     	} else {
 56     		this._thread.join();
 57     	}
 58         return this._exitValue;
 59     },
 60     /**
 61      * Registers an exit callback.
 62      * @param {Function} [fn] An exit callback.
 63      */
 64     registerExitCallback : function(fn) {
 65     	if (this._no == null) {
 66             throw new jls.lang.Exception('This process is no more reachable');
 67     	}
 68     	this._onExitCBs.push(fn);
 69     	if (this._thread == null) {
 70             this._thread = new jls.lang.Thread();
 71             this._thread.run = function() {
 72             	jls.logger.debug('waitFor()...');
 73             	try {
 74                 	this._exitValue = this._no.wait();
 75             	}
 76             	catch (e) {
 77             		this._exitException = e;
 78             	}
 79             	jls.logger.debug('exitCode: ' + this._exitValue);
 80             	this._thread = null;
 81             	this._no = null;
 82             	for (var i = 0; i < this._onExitCBs.length; i++) {
 83                 	if (this._onExitCBs[i]) {
 84                 		this._onExitCBs[i].call(this, this._exitValue);
 85                 	}
 86             	}
 87             };
 88             jls.logger.debug('Start exit callback thread');
 89             this._thread.start(this);
 90     	}
 91         return this;
 92     },
 93     /**
 94      * Unregisters an exit callback.
 95      * @param {Function} [fn] An exit callback.
 96      */
 97     unregisterExitCallback : function(fn) {
 98         for (var i = this._onExitCBs.length - 1; i >= 0; i--) {
 99             if (fn === this._onExitCBs[i]) {
100                 this._onExitCBs.splice(i, 1);
101                 break;
102             }
103         }
104         return this;
105     },
106     /**
107      * Returns this process exit value.
108      * @returns {Number} This process exit value.
109      */
110     exitValue : function() {
111     	if (this._exitValue == jls.lang.Process.STILL_ACTIVE) {
112             throw new jls.lang.Exception('The process is still active');
113     	}
114         return this._exitValue;
115     }
116 });
117 
118 Object.extend(jls.lang.Process,
119 {
120 	DESTROYED: 256,
121 	DETACHED: 257,
122 	STILL_ACTIVE: 259
123 });
124 
125 
126