1 /*!
  2  * 
  3  * JavaLikeScript
  4  * 
  5  */
  6 
  7 // Add default option variable
  8 if (typeof jlsOptions == 'undefined') {
  9     jlsOptions = {};
 10 }
 11 
 12 // Native namespace
 13 var _native = {};
 14 
 15 /*
 16  * Library boot
 17  */
 18 _native.boot = {};
 19 _native.boot.emptyFunction = function() {};
 20 _native.boot.unsupportedFunction = function() {
 21     throw 'Unsupported native operation';
 22 };
 23 _native.boot.unsupportedClass = function() {
 24     throw 'Unsupported native class';
 25 };
 26 _native.boot.log = _native.boot.emptyFunction;
 27 if ((typeof console != 'undefined') && ('log' in console)) {
 28     _native.boot.log = console.log;
 29 }
 30 // Find the default script path
 31 (function() {
 32     var bootstrap = 'bootstrap.js';
 33     var path = '.'; // default
 34     var scriptTags = document.getElementsByTagName('script');
 35     for ( var i = 0; i < scriptTags.length; i++) {
 36         var src = scriptTags[i].getAttribute('src');
 37         if (!src) {
 38             continue;
 39         }
 40         var i = src.lastIndexOf('/' + bootstrap);
 41         if ((i >= 0) && (i == src.length - bootstrap.length - 1)) {
 42             path = src.substring(0, src.length - bootstrap.length - 1);
 43             break;
 44         } else if (src == bootstrap) {
 45             path = '.';
 46             break;
 47         }
 48     }
 49     _native.boot.defaultScriptPath = path;
 50 })();
 51 
 52 
 53 _native.boot.httpRequest = function(url, options) {
 54 	this._url = url;
 55 	this._options = {
 56 	    method : 'post',
 57 	    asynchronous : true,
 58 	    contentType : 'application/x-www-form-urlencoded',
 59 	    encoding : 'UTF-8',
 60 	    parameters : '',
 61 	    user : null,
 62 	    password : null,
 63         onException : _native.boot.emptyFunction,
 64         onFailure : _native.boot.emptyFunction,
 65         onSuccess : _native.boot.emptyFunction
 66 	};
 67 	if (options) {
 68 		for (var key in options) {
 69 			this._options[key] = options[key];
 70 		}
 71 	}
 72 	this._xhr = _native.boot.httpRequest.newXHR();
 73 };
 74 _native.boot.httpRequest.newXHR = function() {
 75 	try {
 76 	    return new XMLHttpRequest()
 77 	}
 78 	catch (e) {
 79 		try {
 80 		    return new ActiveXObject('Msxml2.XMLHTTP')
 81 		}
 82 		catch (e) {
 83 			try {
 84 			    return new ActiveXObject('Microsoft.XMLHTTP')
 85 			}
 86 			catch (e) {
 87 				return false;
 88 			}
 89 		}
 90 	}
 91 };
 92 _native.boot.httpRequest.prototype.getXHR = function() {
 93 	return this._xhr;
 94 };
 95 _native.boot.httpRequest.prototype.getStatus = function() {
 96 	return this._xhr.status || 0;
 97 };
 98 _native.boot.httpRequest.prototype.onStateChange = function() {
 99     var readyState = this._xhr.readyState;
100     _native.core.log(0, '_native.boot.xmlHttpRequest.onStateChange(' + readyState + ')');
101     if (readyState != 4) { // Not completed
102     	return;
103     }
104     var status = this.getStatus();
105     try {
106         if (((status >= 200) && (status < 300)) || (status == 304)) {
107         	this._options.onSuccess.call(this);
108         } else {
109         	this._options.onFailure.call(this);
110         }
111     }
112     catch (e) {
113     	this._options.onException.call(this, e);
114     }
115     finally {
116         this._xhr.onreadystatechange = _native.boot.emptyFunction;
117     }
118 };
119 _native.boot.httpRequest.prototype.send = function() {
120     _native.core.log(0, '_native.boot.xmlHttpRequest.send(), ' + this._options.method + ': "' + this._url + '"');
121 	if ((this._options.user != null) && (this._options.password != null)) {
122 		this._xhr.open(this._options.method.toUpperCase(), this._url,
123 		        this._options.asynchronous, this._options.user,
124 		        this._options.password);
125 	} else {
126 		this._xhr.open(this._options.method.toUpperCase(), this._url,
127 		        this._options.asynchronous);
128 	}
129 	var self = this;
130 	this._xhr.onreadystatechange = function () {
131 	    _native.core.log(0, 'onreadystatechange');
132 		self.onStateChange();
133 	};
134     var headers = {
135     	      'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
136     	    };
137     if (this._options.method == 'post') {
138         headers['Content-type'] = this._options.contentType + (this._options.encoding ? '; charset=' + this._options.encoding : '');
139     }
140     for (var name in headers) {
141         this._xhr.setRequestHeader(name, headers[name]);
142     }
143     var params = (typeof this._options.parameters == 'string') ? this._options.parameters : Object.toQueryString(this._options.parameters);
144 	var body = (this._options.method == 'post') ? (this._options.postBody || params) : null;
145 	this._xhr.send(body);
146     /* Force Firefox to handle ready state 4 for synchronous requests */
147     if (!this._options.asynchronous && this._xhr.overrideMimeType) {
148         this.onStateChange();
149     }
150 	return this;
151 };
152 
153 
154 /*
155  * Library core From "jls generateNativeLibraryAPI.js"
156  */
157 _native.core = {};
158 _native.core.log = function(level, msg) {
159     _native.boot.log(msg);
160 };
161 _native.core.logLevel = _native.boot.emptyFunction;
162 _native.core.exceptionHandler = _native.boot.emptyFunction;
163 _native.core.sleep = _native.boot.emptyFunction;
164 _native.core._scriptPath = [];
165 _native.core.getResourceAsString = function(path) {
166     _native.core.log(0, '_native.core.getResourceAsString("' + path + '")');
167     var text = null;
168     for (var i = 0; i < _native.core._scriptPath.length; i++) {
169         var url = _native.core._scriptPath[i] + '/' + path;
170         _native.core.log(0, 'try url "' + url + '"');
171         var exception = null;
172         var status = 0;
173         new _native.boot.httpRequest(url, {
174             method :'get',
175             asynchronous :false,
176             onException : function(e) {
177                 exception = e;
178             },
179             onFailure : function() {
180                 status = this.getStatus();
181             },
182             onSuccess : function() {
183                 text = this.getXHR().responseText;
184             }
185         }).send();
186         if (exception != null) {
187             throw exception;
188         } else if (status == 0) {
189             break;
190         } else if (status != 404) {
191             throw 'Unsupported status ' + status + ' for script path "' + _native.core._scriptPath[i] + '"';
192         }
193     }
194     if (text == null) {
195         throw 'Script not found "' + path + '"';
196     }
197     return text;
198 };
199 _native.core.getResourceAsByteArray = _native.boot.emptyFunction;
200 _native.core.evalScript = function(path) {
201     _native.core.log(0, '_native.core.evalScript("' + path + '")');
202     eval(_native.core.getResourceAsString(path));
203 };
204 _native.core.loadLibrary = _native.boot.unsupportedFunction;
205 _native.core.visitPaths = _native.boot.emptyFunction;
206 _native.core.gc = _native.boot.unsupportedFunction;
207 _native.core.dumpHead = _native.boot.unsupportedFunction;
208 _native.core.exit = _native.boot.unsupportedFunction;
209 _native.core.halt = _native.boot.unsupportedFunction;
210 _native.core.system = _native.boot.unsupportedFunction;
211 _native.core.signal = _native.boot.unsupportedFunction;
212 _native.core.raise = _native.boot.unsupportedFunction;
213 _native.core.getSignalCounters = _native.boot.unsupportedFunction;
214 _native.core.registerSignalMonitor = _native.boot.unsupportedFunction;
215 _native.core.handleSignal = _native.boot.unsupportedFunction;
216 _native.core.getEnv = _native.boot.unsupportedFunction;
217 _native.core.boot = _native.boot.unsupportedFunction;
218 _native.core.addPath = function(path) {
219     // Check for duplicate
220     var i = _native.core._scriptPath.length;
221     while (--i >= 0) {
222         if (_native.core._scriptPath[i] == path) {
223             break;
224         }
225     }
226     if (i < 0) {
227         _native.core._scriptPath.push(path);
228     }
229 };
230 _native.core.arguments = null;
231 _native.core.properties = { // From "jls systemProperties.js json"
232   'cpu.endian' : 'little',
233   'cpu.pointer.size' : '4',
234   'file.encoding' : 'UTF-8',
235   'file.separator' : '/',
236   'javascript.engine' : '?',
237   'javascript.version' : '180',
238   'jls.bootstrap.filename' : 'bootstrap.js',
239   'jls.extension.path' : '',
240   'jls.home' : '.',
241   'jls.library.path' : '.',
242   'jls.logger.logLevel' : 'warn',
243   'jls.programname' : 'jls',
244   'jls.script.path' : _native.boot.defaultScriptPath,
245   'jls.vendor' : 'spyl',
246   'jls.vendor.url' : 'http://javalikescript.free.fr/',
247   'jls.version' : '0.1',
248   'line.separator' : '\n',
249   'path.separator' : ';',
250   'user.dir' : '.',
251   'user.home' : '.',
252   'user.name' : '?'
253 };
254 _native.core.SIGINT = 2;
255 _native.core.SIGILL = 4;
256 _native.core.SIGFPE = 8;
257 _native.core.SIGSEGV = 11;
258 _native.core.SIGTERM = 15;
259 _native.core.SIGBREAK = 21;
260 _native.core.SIGABRT = 22;
261 _native.core.SIG_ERR = -1;
262 _native.core.SIG_DFL = 0;
263 _native.core.SIG_IGN = 1;
264 _native.core.SIG_USR = 2;
265 /*
266  * Class _native.core.ByteArray
267  */
268 _native.core.ByteArray = function(capacity, adoptable) {
269     this._array = null;
270     this._readOnly = false;
271     if (typeof capacity == 'number') {
272         if (typeof adoptable == 'number') {
273             throw 'Unsupported native operation (new ByteArray from pointer)';
274         }
275         this._array = new Array(capacity);
276     } else if (typeof capacity == 'string') {
277         this._array = new Array(/*capacity.length * 2*/);
278     	for (var i = 0; i < capacity.length; i++) {
279     		var c = capacity.charCodeAt(i);
280             this._array.push(c & 0xff);
281             this._array.push((c >>> 8) & 0xff);
282     	}
283         _native.core.log(0, 'ByteArray.construct(), this._array.length: ' + this._array.length);
284         this._readOnly = ! adoptable;
285     } else {
286         throw 'Illegal argument type ' + (typeof capacity);
287     }
288 };
289 _native.core.ByteArray.prototype.free = function() {
290     this._array = null;
291 };
292 _native.core.ByteArray.prototype.size = function() {
293     return this._array.length;
294 };
295 _native.core.ByteArray.prototype.put = function(offset, value) {
296     this._array[offset] = value & 0xff;
297 };
298 _native.core.ByteArray.prototype.get = function(offset) {
299     return this._array[offset];
300 };
301 _native.core.ByteArray.prototype.putString = _native.boot.unsupportedFunction; // TODO
302 _native.core.ByteArray.prototype.getString = _native.boot.unsupportedFunction; // TODO
303 _native.core.ByteArray.prototype.putChars = _native.boot.unsupportedFunction; // TODO
304 _native.core.ByteArray.prototype.getChars = function(at, length) {
305     var s = '';
306     for (var i = at; i < length; i++) {
307         var c = this._array[i * 2] | (this._array[i * 2 + 1] << 8);
308         s += String.fromCharCode(c);
309     }
310     return s;
311 };
312 _native.core.ByteArray.prototype.toNewChars = function(length) {
313     return this.getChars(0, length);
314 };
315 _native.core.ByteArray.prototype.pointer = _native.boot.unsupportedFunction;
316 _native.core.ByteArray.prototype.memcpy = function(offset, byteArray, at, length) {
317     _native.core.log(0, 'ByteArray.memcpy(' + offset + ', ?, ' + at + ', ' + length + ')');
318     for (var i = 0; i < length; i++) {
319         this._array[offset + i] = byteArray._array[at + i];
320     }
321 };
322 _native.core.ByteArray.prototype.setPointer = _native.boot.unsupportedFunction;
323 _native.core.ByteArray.prototype.resetPointer = _native.boot.unsupportedFunction;
324 _native.core.ByteArray.prototype.isReadOnly = function() {
325     return this._readOnly;
326 };
327 /*
328  * Unsupported classes
329  */
330 _native.core.Thread = _native.boot.unsupportedClass;
331 _native.core.Lock = _native.boot.unsupportedClass;
332 _native.core.Monitor = _native.boot.unsupportedClass;
333 _native.core.Process = _native.boot.unsupportedClass;
334 _native.core.ProcessAttr = _native.boot.unsupportedClass;
335 
336 // Update script path
337 if ('arguments' in jlsOptions) {
338     _native.core.arguments = jlsOptions.arguments;
339 }
340 // Update properties
341 if ('properties' in jlsOptions) {
342 	for (var name in jlsOptions.properties) {
343 		_native.core.properties[name] = jlsOptions.properties[name];
344 	}
345 }
346 // Update script path
347 _native.core._scriptPath = _native.core.properties['jls.script.path'].split(/[;:]/);
348 
349 
350 /**
351  * jls Base framework.
352  * All the framework objects are created under the jls namespace.
353  * The default objects are extended using prototype like behaviors.
354  * 
355  * @namespace
356  * @see jls.lang
357  */
358 var jls = {};
359 
360 /**
361  * @namespace Provides base classes for the jls language.
362  * @see jls.lang.Exception
363  * @see jls.lang.Logger
364  * @see jls.lang.ClassLoader
365  */
366 jls.lang = {};
367 
368 // Load prototype light
369 _native.core.evalScript('plight.js');
370 
371 // Load base classes
372 _native.core.evalScript('jls/lang/Exception.js');
373 _native.core.evalScript('jls/lang/Logger.js');
374 
375 /**
376  * Logger.
377  * 
378  * @type jls.lang.Logger
379  * @memberOf jls
380  */
381 jls.logger = new jls.lang.Logger(jls.lang.Logger.WARN);
382 if ('jls.logger.logLevel' in _native.core.properties) {
383     jls.logger.setLogLevel(_native.core.properties['jls.logger.logLevel']);
384 }
385 
386 _native.core.evalScript('jls/lang/ClassLoader.js');
387 
388 /**
389  * ClassLoader.
390  * 
391  * @type jls.lang.ClassLoader
392  * @memberOf jls
393  */
394 jls.loader = new jls.lang.ClassLoader();
395 
396 // Register base classes
397 jls.loader.provide('jls.lang.Exception', true);
398 jls.loader.provide('jls.lang.Logger', true);
399 jls.loader.provide('jls.lang.ClassLoader', true);
400 
401