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