1 //jls.loader.provide('jls.lang.ClassLoader'); 2 3 /** 4 * @class A class loader is an object that is responsible for loading classes. 5 */ 6 jls.lang.ClassLoader = jls.lang.Class.create(/** @lends jls.lang.ClassLoader.prototype */ 7 { 8 initialize : function() { 9 this._cache = {}; 10 this._loadedLibraries = {}; 11 }, 12 /** 13 * Loads a native library compliant with the JLS native engine. 14 * 15 * @param {String} name The name of the library to load. 16 */ 17 requireLibrary : function(libname) { 18 if (libname in this._loadedLibraries) { 19 return; 20 } 21 try { 22 _native.core.loadLibrary(libname); 23 this._loadedLibraries[libname] = true; 24 } catch (e) { 25 throw e; 26 } 27 }, 28 /** 29 * Declares that a class is about to be provided. 30 * 31 * @param {String} classname The classname that is provided. 32 */ 33 provide : function(classname, exists) { 34 if (classname in this._cache) { 35 //throw new jls.lang.Exception('Class ' + classname + ' already provided.'); 36 jls.logger.warn('Class ' + classname + ' already provided.'); 37 return; 38 } 39 jls.lang.ClassLoader.createPackage(classname); 40 jls.logger.debug('provide(\"' + classname + '\")'); 41 if (exists) { 42 this._cache[classname] = eval(classname); 43 } else { 44 this._cache[classname] = true; // in progress 45 } 46 }, 47 /** 48 * Declares a class requirement. If that class has not yet been provided then it is loaded. 49 * 50 * @param {String} classname The classname that is required. 51 */ 52 require : function(classname) { 53 if (classname in this._cache) { 54 if (this._cache[classname] === true) { 55 //jls.logger.warn('class \"' + classname + '\" provided but not yet created'); 56 return null; 57 } 58 return this._cache[classname]; 59 } 60 var path = jls.lang.ClassLoader.getClassFilename(classname, '.js'); 61 jls.logger.debug('Loading class \"' + classname + '\", evalScript: \"' + path + '\"'); 62 _native.core.evalScript(path); 63 if (! (classname in this._cache)) { 64 throw new jls.lang.Exception('class not provided ' + classname); 65 } else { 66 jls.logger.debug('class ' + classname + ' provided'); 67 } 68 this._cache[classname] = eval(classname); 69 return this._cache[classname]; 70 }, 71 getClass : function(name) { 72 for (var name in this._cache) { 73 return this._cache[name]; 74 } 75 return null; 76 }, 77 getClassname : function(obj) { 78 for (var name in this._cache) { 79 if (this._cache[name] === obj.constructor) { 80 return name; 81 } 82 } 83 return null; 84 }, 85 // TODO Find the right place for this method 86 // fn must be function(name) 87 visitPaths : function(fn) { 88 _native.core.visitPaths(fn); 89 } 90 }); 91 92 Object.extend(jls.lang.ClassLoader, /** @lends jls.lang.ClassLoader */ 93 { 94 getClassFilename : function(name, extension) { 95 return name.replace(/\./g, '/') + extension; 96 }, 97 createPackage : function(packagename) { 98 var packagenames = packagename.split('.'); 99 var name = ''; 100 for (var i = 0; i < packagenames.length - 1; i++) { 101 if (i > 0) { 102 name += '.'; 103 } 104 name += packagenames[i]; 105 var packagetype = eval('typeof ' + name); 106 //jls.logger.debug('Package \"' + name + '\": ' + packagetype); 107 if (packagetype == 'undefined') { 108 eval(name + ' = {};'); 109 } else if (packagetype != 'object') { 110 throw new jls.lang.Exception('Invalid package \"' + packagename + '\".'); 111 } 112 } 113 } 114 }); 115