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 jls.logger.debug(classname + ' providing in progress'); 46 } 47 }, 48 /** 49 * Declares a class requirement. If that class has not yet been provided then it is loaded. 50 * 51 * @param {String} classname The classname that is required. 52 */ 53 require : function(classname) { 54 if (classname in this._cache) { 55 if (this._cache[classname] === true) { 56 //jls.logger.warn('class \"' + classname + '\" provided but not yet created'); 57 return null; 58 } 59 return this._cache[classname]; 60 } 61 var path = jls.lang.ClassLoader.getClassFilename(classname, '.js'); 62 jls.logger.debug('Loading class \"' + classname + '\", evalScript: \"' + path + '\"'); 63 _native.core.evalScript(path); 64 if (! (classname in this._cache)) { 65 throw new jls.lang.Exception('class not provided ' + classname); 66 } else { 67 jls.logger.debug('class ' + classname + ' provided'); 68 } 69 this._cache[classname] = eval(classname); 70 return this._cache[classname]; 71 }, 72 getClass : function(name) { 73 for (var name in this._cache) { 74 return this._cache[name]; 75 } 76 return null; 77 }, 78 getClassname : function(obj) { 79 for (var name in this._cache) { 80 if (this._cache[name] === obj.constructor) { 81 return name; 82 } 83 } 84 return null; 85 }, 86 // TODO Find the right place for this method 87 // fn must be function(name) 88 visitPaths : function(fn) { 89 _native.core.visitPaths(fn); 90 } 91 }); 92 93 Object.extend(jls.lang.ClassLoader, /** @lends jls.lang.ClassLoader */ 94 { 95 getClassFilename : function(name, extension) { 96 return name.replace(/\./g, '/') + extension; 97 }, 98 createPackage : function(packagename) { 99 var packagenames = packagename.split('.'); 100 var name = ''; 101 for (var i = 0; i < packagenames.length - 1; i++) { 102 if (i > 0) { 103 name += '.'; 104 } 105 name += packagenames[i]; 106 var packagetype = eval('typeof ' + name); 107 //jls.logger.debug('Package \"' + name + '\": ' + packagetype); 108 if (packagetype == 'undefined') { 109 eval(name + ' = {};'); 110 } else if (packagetype != 'object') { 111 throw new jls.lang.Exception('Invalid package \"' + packagename + '\".'); 112 } 113 } 114 } 115 }); 116