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