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