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