Changeset 67

Show
Ignore:
Timestamp:
07/19/06 17:29:03 (2 years ago)
Author:
Jan-Klaas Kollhof
Message:

created experimental branch

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/experimental/jsolait/jsolait.js

    r61 r67  
    1 /* 
    2     Copyright (c) 2003-2005 Jan-Klaas Kollhof 
    3  
    4     This file is part of the JavaScript O Lait library(jsolait). 
    5  
    6     jsolait is free software; you can redistribute it and/or modify 
    7     it under the terms of the GNU Lesser General Public License as published by 
    8     the Free Software Foundation; either version 2.1 of the License, or 
    9     (at your option) any later version. 
    10  
    11     This software is distributed in the hope that it will be useful, 
    12     but WITHOUT ANY WARRANTY; without even the implied warranty of 
    13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
    14     GNU Lesser General Public License for more details. 
    15  
    16     You should have received a copy of the GNU Lesser General Public License 
    17     along with this software; if not, write to the Free Software 
    18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
    19 */ 
    20  
    21 /** 
    22     The main jsolait script. 
    23     It provides the core functionalities for creating classes, modules and for importing modules. 
    24  
    25     @author Jan-Klaas Kollhof 
    26     @version 2.0 
    27     @lastchangedby $LastChangedBy$ 
    28     @lastchangeddate $Date$ 
    29     @revision $Revision$ 
    30 **/ 
    31  
    32  
    33 /** 
    34     Creates a new class object which inherits from superClass. 
    35     @param name="anonymous"  The name of the new class. 
    36                                             If the created class is a public member of a module then 
    37                                             the __name__ property of that class is automatically set by Module(). 
    38     @param base1 *                  The base classes (not an array but one argument per base class). 
    39     @param classScope(-1)        A function which is executed for class construction. 
    40                                             As 1st parameter it will get the new class' protptype for 
    41                                             overrideing or extending the super class. As 2nd parameter it will get 
    42                                             the super class' wrapper for calling inherited methods. 
    43 **/ 
    44 Class=function(name, base1, classScope){ 
    45     var args=[]; 
    46     for(var i=0;i<arguments.length;i++){ 
    47         args[i] = arguments[i]; 
    48     } 
    49  
    50     classScope = args.pop(); 
    51     var classID =  Class.__idcount__++; 
    52  
    53     if((args.length>0) && (typeof args[0] =='string')){ 
    54         name=args.shift(); 
    55     }else{ 
    56         name="anonymous" + classID; 
    57     } 
    58  
    59     var bases = args; 
    60  
    61     //set up the 'public static' fields of the class 
    62     var __class__={__isArray__ : false, 
    63                          __name__ : name, 
    64                          __bases__: bases, 
    65                          __id__: '@' + classID, 
    66                          __str__ : function(){ 
    67                             return "[class %s]".format(this.__name__); 
    68                          } 
    69                     }; 
    70  
    71     var baseProtos=[];//stores the prototypes of all the base classes 
    72     var proto; //the prototype to use for the new class 
    73     if(bases.length==0){//use Object as base 
    74         proto={}; 
    75         proto.__str__ = function(){ 
    76             return "[%s %s]".format(this.__class__.prototype.__call__ === undefined ? 'object' : 'callable', this.__class__.__name__); 
    77         }; 
    78         __class__.__bases__=[Object]; 
    79     }else{ //inherit from all base classes 
    80         var baseProto; 
    81         for(var i=0;i<bases.length;i++){ 
    82             var baseClass = bases[i]; 
    83             //remember the base prototypes 
    84             baseProtos.push(baseClass.prototype); 
    85             if(baseClass.__createProto__ !== undefined){ 
    86                 baseProto = baseClass.__createProto__(bases); 
    87             }else{ 
    88                 baseProto = new baseClass(Class); 
    89             } 
    90             __class__.__isArray__ = __class__.__isArray__ || baseClass.__isArray__; 
    91  
    92             if(i==0){//for the first base class just use it's proto as the final proto 
    93                 proto = baseProto; 
    94             }else{//for all others extend(do not overwrite) the final proto with the properties in the baseProto 
    95                 for(var key in baseProto){ 
    96                     if(proto[key] === undefined){ 
    97                         proto[key] = baseProto[key]; 
    98                     } 
    99                 } 
    100             } 
    101             //extend the new class' static interface 
    102             //todo: any props that should not be copied 
    103             for(var key in baseClass){ 
    104                 if((key != 'prototype') && (__class__[key] === undefined)){ 
    105                     __class__[key] = baseClass[key]; 
    106                 } 
    107             } 
    108         } 
    109     } 
    110     //make sure all jsolait objects have a id method 
    111     if(proto.__id__ === undefined){ 
    112         proto.__id__=function(){ 
    113             this.__id__ = '@' + (Class.__idcount__++); 
    114             return this.__id__; 
    115         }; 
    116     } 
    117     proto.__class__=__class__; 
    118  
    119     //run the class setup function provided as classScope 
    120     if(classScope.length-1 > baseProtos.length){ 
    121         var privId = '__priv__' + __class__.__id__; 
    122         classScope.apply(this,[proto, privId].concat(baseProtos)); 
    123     }else{ 
    124         classScope.apply(this,[proto].concat(baseProtos)); 
    125     } 
    126      
    127     //make sure the toString points to __str__, this will make overwriting __str__ after object construction impossible (todo ?) 
    128     //but will be faster than having toString call __str__, also overwriting methods unless they are ment to be overridden is not cool anyways. 
    129     proto.toString=proto.__str__; 
    130          
    131     //allthough a single constructor would suffice for generating normal objects, Arrays and callables, 
    132     //we use 3 different ones. This will minimize the code inside the constructor and therefore 
    133     //minimize object construction time 
    134     if(proto.__call__){ 
    135         //if the callable interface is implemented we need a class constructor 
    136         //which generates a function upon construction 
    137         var NewClass = function(calledBy){ 
    138             if(calledBy !== Class){ 
    139                 var rslt = function(){ 
    140                     return rslt.__call__.apply(rslt, arguments); 
    141                 }; 
    142                  
    143                 //this will only work for the current class but not create any priv objects for any base class  
    144                 var proto=arguments.callee.prototype; 
    145                 for(var n in proto){ 
    146                     rslt[n] = proto[n]; 
    147                 } 
    148                 rslt.constructor = proto.__class__; 
    149                 rslt.toString = proto.__str__; 
    150                 if(rslt.__init__){ 
    151                     rslt.__init__.apply(rslt, arguments); 
    152                 } 
    153                 return rslt; 
    154             } 
    155         }; 
    156     }else if(__class__.__isArray__){ 
    157         //Since we cannot inherit from Array directly we take the same approach as with the callable above 
    158         //and just have a constructor which creates an Array 
    159         var NewClass = function(calledBy){ 
    160             if(calledBy !== Class){ 
    161                 rslt=[]; 
    162  
    163                 var proto=arguments.callee.prototype; 
    164                 for(var n in proto){ 
    165                     rslt[n] = proto[n]; 
    166                 } 
    167                 rslt.constructor = proto.__class__; 
    168                 rslt.toString = proto.__str__; 
    169                 if(rslt.__init__){ 
    170                     rslt.__init__.apply(rslt, arguments); 
    171                 }else{//implement Array's default behavior 
    172                     if(arguments.length==1){ 
    173                         rslt.length=arguments[0]; 
    174                     }else{ 
    175                         for(var i=0;i<arguments.length;i++){ 
    176                             rslt.push(arguments[i]); 
    177                         } 
    178                     } 
    179                 } 
    180                 return rslt; 
    181             } 
    182         };  
    183     }else{ 
    184         //this is a 'normal' object constructor which does nothing but call the __init__ method 
    185         //unless it does not exsit or the constructor was used for prototyping 
    186         var NewClass = function(calledBy){ 
    187             if(calledBy !== Class){ 
    188                 if(this.__init__){ 
    189                     this.__init__.apply(this, arguments); 
    190                 } 
    191             } 
    192         }; 
    193     } 
    194  
    195     //reset the constructor for new objects to the actual constructor. 
    196     proto.constructor = NewClass; 
    197     proto.__class__= NewClass;//no, it is not needed, just like __str__ is not, but it is nicer than constructor 
    198          
    199     //this is where the inheritance realy happens 
    200     NewClass.prototype = proto; 
    201  
    202     //apply all the static fileds 
    203     for(var key in __class__){ 
    204         NewClass[key] = __class__[key]; 
    205     } 
    206     NewClass.toString=__class__.__str__; 
    207  
    208     return NewClass; 
    209 }; 
    210 Class.__idcount__=0; 
    211 Class.__str__=Class.toString = function(){return "[object Class]";}; 
    212 Class.__createProto__=function(){ throw "Can't use Class as a base class.";}; 
    213  
    214 Function.__createProto__ = function(){ throw "Cannot inherit from Function. implement the callable interface instead using YourClass::__call__.";}; 
    215 Array.__createProto__=function(){ var r =[]; r.__str__ = Array.prototype.toString;  return r; }; 
    216 Array.__isArray__=true; 
    217 Array.__str__=Array.toString=function(){return "[class Array]";}; 
    218 Object.__str__=Object.toString=function(){return "[class Object]";}; 
    219 Number.__str__ =Number.toString=function(){return "[class Number]";}; 
    220 String.__str__ =String.toString=function(){return "[class String]";}; 
    221  
    222 /** 
    223     Returns a string representation of an object. 
    224     @param obj  The object to return a string repr. of. 
    225     @return A string repr. the object. 
    226 **/ 
    227 str = String; 
    228  
    229 /** 
    230     Return a String containing a printable representation of an object which can be used with eval() to create an equal object. 
    231     Objects can cosutumize the the value being returned by repr(obj) by providing a obj.__repr__() method which is called by repr(obj). 
    232     @param obj  The object to create a repr. String from. 
    233     @return A representation of the object. 
    234 **/ 
    235 repr = function(obj){ 
    236     if(obj == null){ 
    237         return null; 
    238     }else if(obj.__repr__){ 
    239         return obj.__repr__(); 
    240     }else{ 
    241         switch(typeof obj){ 
    242             case "string": 
    243                 obj = obj.replace(/\\/g,"\\\\").replace(/\"/g,"\\\"").replace(/\n/g, "\\n").replace(/\r/g,"\\r"); 
    244                 return '"' + obj + '"'; 
    245             case "boolean":case"number": 
    246                 return "" + obj; 
    247             case "object": 
    248                 var out = []; 
    249                 if(obj == null){ 
    250                     return "null"; 
    251                 }else if(obj instanceof Array){ 
    252                     for(var i=0;i<obj.length;i++){ 
    253                         out.push(repr(obj[i])); 
    254                     } 
    255                     return "[" + out.join(",") + "]"; 
    256                 }else if(obj instanceof Object){ 
    257                     for(var key in obj){ 
    258                         out.push(repr(key) + ":" + repr(obj[key])); 
    259                     } 
    260                     return "{" + out.join(",") + "}"; 
    261                 } 
    262         } 
    263     } 
    264 }; 
    265  
    266 /** 
    267     Returns a unique id for an object. 
    268     The same object will always return the same id.  
    269     Most objects are id-able. The following steps are taken to find an id. 
    270     If the obj has an __id__ property that id will be returned. (all jsolait classes have an __id__ property) 
    271     If the obj has a __id__ method the return value of that method will be returned.(all jsolait objects have a __id__ method which sets an __id__ property) 
    272     If the obj is a String  the string prefixed with $ is returned. 
    273     If the obj is a Number the number prefixed with a # is returned as a string. 
    274     All other objects are not safely id-able and an exception is thrown unless forceId is true. In that case the object will get a unique __id__ property applied which is returned. 
    275      
    276     @param obj The object to get the id for. 
    277     @param forceId=false if true it forces id() to set an __id__ property onto a non id-able object, making it id-able. 
    278     @return A String containing a id value for the obj. 
    279 **/ 
    280 id = function(obj, forceId){ 
    281     switch(typeof obj.__id__){ 
    282          
    283         case "undefined": 
    284             if(obj instanceof String || typeof obj == 'string'){ 
    285                 return '$' + obj; 
    286             }else if(obj instanceof Number || typeof obj == 'number'){ 
    287                 return '#' + obj; 
    288             }else if(forceId){ 
    289                 obj.__id__ = '@' + (Class.__idcount__++); 
    290                 return obj.__id__; 
    291             }else{ 
    292                 throw new jsolait.Exception('Objec cannot be IDed: %s'.format(obj)); 
    293             } 
    294          
    295         case "function": 
    296             return obj.__id__(); 
    297          
    298         default: //string 
    299             return obj.__id__; 
    300     } 
    301 }; 
    302  
    303 /** 
    304     Returns a bound method. 
    305     A bound method is a function which is bound to a specific object. 
    306     Calling the bound method will call the given function with the this-object inside that function's scope being the object specified. 
    307      
    308     @param obj  The object the function should be bound to. 
    309     @param fn   A function object the obj will be bound to. 
    310     @return A method which when run executes the function with the this-object being the obj specified. 
    311 **/ 
    312 bind = function(obj, fn){ 
    313     return function(){ 
    314         return fn.apply(obj, arguments); 
    315     }; 
    316 }; 
    317  
    318 /** 
    319     Returns if an object is an instance of a specified class or of a direct or indirect subclass thereof. 
    320      
    321     It also works for traditional javascript inheritance(i.e. SomeClass=function(){}; SomeClass.prototype=new SuperClass(); ...). 
    322     Internaly it first checks using instanceof if that fails it uses isinstance(obj.constructor, cls). 
    323     There are some differences between using isinstance and instanceof. 
    324     i.e.  
    325     (123 instanceof Number) == false; 
    326     isinstance(123, Number) == true; 
    327     ('abc' instanceof String) == false; 
    328     isinstance('abc', String) == true; 
    329         
    330     @param obj   The object to test. 
    331     @param cls     The class to test against. 
    332     @return True if the object is an instance of cls. False otherwise. 
    333 **/ 
    334 isinstance=function(obj, cls){ 
    335     if(obj instanceof cls){ 
    336         return true; 
    337     }else{ 
    338         return issubclass(obj.constructor, cls); 
    339     } 
    340 }; 
    341  
    342 /** 
    343     Returns if a cls is a direct or indirect subclass of another. 
    344      
    345     A class is always a subclass of itself and Object is the base for all classes. 
    346     A class is a subclass of baseclass if it's prototype is an instance of baseclass. 
    347     A class is a subclass of baseclass if any of it's __bases__ is a subclass of baseclass. 
    348     If there are no __bases__ defined there is no way to findout about inheritance besides  
    349     the prototype chain which was checked by instanceof before, so false is returned. 
    350      
    351     @param cls  The class to test. 
    352     @param baseclass  The assumed superclass. 
    353     @return True if cls is a subclass of baseclass otherwise false. 
    354 **/ 
    355 issubclass=function(cls, baseclass){ 
    356     if(baseclass === Object || cls===baseclass || (cls.prototype instanceof baseclass)){ 
    357         return true; 
    358     }else{ 
    359         var bases = cls.__bases__; 
    360         if(bases != null){ 
    361             for(var i=0;i<bases.length;i++){ 
    362                 if(bases[i] === baseclass){ 
    363                     return true; 
    364                 } 
    365             } 
    366             for(var i=0;i<bases.length;i++){ 
    367                 if(issubclass(bases[i], baseclass)){ 
    368                     return true; 
    369                 } 
    370             } 
    371         } 
    372         return false; 
    373     } 
    374 }; 
    375  
    376  
    377 /** 
    378     Creates a new module and registers it. 
    379     @param name              The name of the module. 
    380     @param version            The version of a module. 
    381     @param moduleScope    A function which is executed for module creation. 
    382                                      As 1st parameter it will get the module variable. 
    383                                      The imported modules(imports) will be passed to the moduleScope starting with the 2nd parameter. 
    384 **/ 
    385 Module=function(name, version, moduleScope){ 
    386     var newMod = new Module.ModuleClass(name, version, Module.currentURI); 
    387      
    388     try{//to execute the scope of the module 
    389         moduleScope.call(newMod, newMod); 
    390     }catch(e){ 
    391         throw new Module.ModuleScopeExecFailed(newMod, e); 
    392     } 
    393      
    394     //set __name__  for methods and classes 
    395     for(var n in newMod){ 
    396         var obj = newMod[n]; 
    397         if(typeof obj == 'function'){ 
    398             obj.__name__ = n; 
    399         } 
    400     } 
    401      
    402     jsolait.registerModule(newMod); 
    403     return newMod; 
    404 }; 
    405  
    406 Module.ModuleClass=Class(function(publ){ 
    407     publ.name; 
    408     publ.version; 
    409     publ.__sourceURI__; 
    410     publ.Exception; 
    411      
    412     publ.__init__=function(name,version,sourceURI){ 
    413         this.name=name; 
    414         this.version=version; 
    415         this.__sourceURI__ = sourceURI; 
    416         this.Exception = Class(Module.Exception, function(){}); 
    417         this.Exception.prototype.module = this; 
    418     }; 
    419      
    420     publ.__str__=function(){ 
    421         //todo:SVN adaption 
    422         return "[module '%s' version: %s]".format(this.name, (this.version+'').replace(/\$Revision:\s(\d+) \$/, "rev.$1")); 
    423     }; 
    424 }); 
    425  
    426  
    427 Module.toString=function(){ 
    428     return "[object Module]"; 
    429 }; 
    430  
    431 Module.__createProto__=function(){ 
    432     throw "Can't use Module as a base class."; 
    433 }; 
    434  
    435  
    436 /** 
    437     Base class for all module-Exceptions. 
    438     This class should not be instaciated directly but rather 
    439     use the exception that is part of the module. 
    440 **/ 
    441 Module.Exception=Class("Exception", function(publ){ 
    442     /** 
    443         Initializes a new Exception. 
    444         @param msg           The error message for the user. 
    445         @param trace=undefined  The error causing this Exception if available. 
    446     **/ 
    447     publ.__init__=function(msg, trace){ 
    448         this.name = this.constructor.__name__; 
    449         this.message = ''+msg; 
    450         this.trace = trace; 
    451     }; 
    452  
    453     publ.__str__=function(){ 
    454         return this.toTraceString(); 
    455     }; 
    456      
    457     /** 
    458         Returns the complete trace of the exception. 
    459         @param indent=0  The indention to use for each line. 
    460         @return The error trace. 
    461     **/ 
    462     publ.toTraceString=function(indent){ 
    463         indent = indent==null ? 0 : indent; 
    464  
    465         //todo:use  constructor.__name__? 
    466         var s="%s in %s:\n%s".format(this.name, this.module, this.message.indent(4)).indent(indent); 
    467         if(this.trace){ 
    468             if(this.trace.toTraceString){ 
    469                 s+=('\n\nbecause:\n'+ this.trace.toTraceString(indent + 4)); 
    470             }else{ 
    471                 s+=(this.trace +'\n').indent(indent+4); 
    472             } 
    473         } 
    474         return s; 
    475     }; 
    476  
    477     ///The name of the Exception. 
    478     publ.name;//todo is that needed? 
    479     ///The error message. 
    480     publ.message; 
    481     ///The module the Exception belongs to. 
    482     publ.module="jsolait"; 
    483     ///The error which caused the Exception or undefined. 
    484     publ.trace; 
    485 }); 
    486  
    487 /** 
    488     Thrown if a module scope could not be run. 
    489 **/ 
    490 Module.ModuleScopeExecFailed=Class("ModuleScopeExecFailed", Module.Exception, function(publ, supr){ 
    491     /** 
    492         Initializes a new ModuleScopeExecFailed Exception. 
    493         @param module      The module. 
    494         @param trace      The error cousing this Exception. 
    495     **/ 
    496     publ.__init__=function(module, trace){ 
    497         supr.__init__.call(this, "Failed to run the module scope for %s".format(module), trace); 
    498         this.failedModule = module; 
    499     }; 
    500     ///The module that could not be createed. 
    501     publ.module; 
    502 }); 
    503  
    504  
    505 /** 
    506  
    507     @author                 Jan-Klaas Kollhof 
    508     @lastchangedby       $LastChangedBy$ 
    509     @lastchangeddate    $Date$ 
    510 **/ 
    511 Module("jsolait", "$Revision$", function(mod){ 
    512     jsolait=mod; 
    513      
    514     mod.modules={}; 
    515  
    516     ///The paths of  the modules that come with jsolait. 
     1jsolait=(function(){ 
     2    jsolait = {}; 
     3     
     4    jsolait.__name__='jsolait'; 
     5     
     6    jsolait.__version__="$Revision$"; 
     7     
     8    jsolait.__str__ =function(){ 
     9        return "[module '%s' version: %s]".format(this.__name__, (this.__version__+'').replace(/\$Revision:\s(\d+) \$/, "Rev.$1")); 
     10    }; 
     11    jsolait.toString=jsolait.__str__; 
     12     
     13    ///The location where jsolait is installed. 
    51714    //do not edit the following lines, it will be replaced by the build script 
    518     /*@moduleURIs begin*/ 
    519     mod.knownModuleURIs={"codecs":"%(baseURI)s/lib/codecs.js", 
    520                                         "crypto":"%(baseURI)s/lib/crypto.js", 
    521                                         "dom":"%(baseURI)s/lib/dom.js", 
    522                                         "forms":"%(baseURI)s/lib/forms.js", 
    523                                         "iter":"%(baseURI)s/lib/iter.js", 
    524                                         "jsonrpc":"%(baseURI)s/lib/jsonrpc.js", 
    525                                         "lang":"%(baseURI)s/lib/lang.js", 
    526                                         "net":"%(baseURI)s/lib/net", 
    527                                         "sets":"%(baseURI)s/lib/sets.js", 
    528                                         "testing":"%(baseURI)s/lib/testing.js", 
    529                                         "urllib":"%(baseURI)s/lib/urllib.js", 
    530                                         "xml":"%(baseURI)s/lib/xml.js", 
    531                                         "xmlrpc":"%(baseURI)s/lib/xmlrpc.js"}; 
    532     /*@moduleURIs end*/ 
    533  
     15    /*@baseURI begin*/ 
     16    jsolait.baseURI="./jsolait"; 
     17    /*@baseURI end*/ 
     18         
     19    ///The paths to the modules that come with jsolait. 
     20    //do not edit the following lines, it will be replaced by the build script 
     21    /*@moduleSourceURIs begin*/ 
     22    jsolait.moduleSourceURIs={}; 
     23    /*@moduleSourceURIs end*/ 
    53424     
    53525    /** 
     
    53828        they may contain StringFormating symbols e.g '%(baseURI)s/lib' 
    53929    **/ 
    540     mod.moduleSearchURIs = ["."]; 
    541  
    542     ///The location where jsolait is installed. 
    543     //do not edit the following lines, it will be replaced by the build script 
    544     /*@baseURI begin*/ 
    545     mod.baseURI="./jsolait"; 
    546     /*@baseURI end*/ 
    547      
    548     mod.packagesURI = "%(baseURI)s/packages"; 
     30    jsolait.moduleSearchURIs = [".", "%(baseURI)s/lib"]; 
     31    
     32    jsolait.packagesURI = "%(baseURI)s/packages"; 
     33     
     34    jsolait.modules={}; 
     35     
     36    /** 
     37        Creates a new class object which inherits from superClass. 
     38        @param name="anonymous"  The name of the new class. 
     39                                                If the created class is a public member of a module then 
     40                                                the __name__ property of that class is automatically set by Module(). 
     41        @param base1 *                  The base classes (not an array but one argument per base class). 
     42        @param classScope(-1)        A function which is executed for class construction. 
     43                                                As 1st parameter it will get the new class' protptype for 
     44                                                overrideing or extending the super class. As 2nd parameter it will get 
     45                                                the super class' wrapper for calling inherited methods. 
     46    **/ 
     47    var Class=function(name, base1, classScope){ 
     48        var args=[]; 
     49        for(var i=0;i<arguments.length;i++){ 
     50            args[i] = arguments[i]; 
     51        } 
     52 
     53        classScope = args.pop(); 
     54        var classID =  Class.__idcount__++; 
     55 
     56        if((args.length>0) && (typeof args[0] =='string')){ 
     57            name=args.shift(); 
     58        }else{ 
     59            name="anonymous" + classID; 
     60        } 
     61 
     62        var bases = args; 
     63 
     64        //set up the 'public static' fields of the class 
     65        var __class__={__isArray__ : false, 
     66                             __name__ : name, 
     67                             __bases__: bases, 
     68                             __id__: '@' + classID, 
     69                             __str__ : function(){ 
     70                                return "[class %s]".format(this.__name__); 
     71                             } 
     72                        }; 
     73 
     74        var baseProtos=[];//stores the prototypes of all the base classes 
     75        var proto; //the prototype to use for the new class 
     76        if(bases.length==0){//use Object as base 
     77            proto={}; 
     78            proto.__str__ = function(){ 
     79                return "[%s %s]".format(this.__class__.prototype.__call__ === undefined ? 'object' : 'callable', this.__class__.__name__); 
     80            }; 
     81            __class__.__bases__=[Object]; 
     82        }else{ //inherit from all base classes 
     83            var baseProto; 
     84            for(var i=0;i<bases.length;i++){ 
     85                var baseClass = bases[i]; 
     86                //remember the base prototypes 
     87                baseProtos.push(baseClass.prototype); 
     88                if(baseClass.__createProto__ !== undefined){ 
     89                    baseProto = baseClass.__createProto__(bases); 
     90                }else{ 
     91                    baseProto = new baseClass(Class); 
     92                } 
     93                __class__.__isArray__ = __class__.__isArray__ || baseClass.__isArray__; 
     94 
     95                if(i==0){//for the first base class just use it's proto as the final proto 
     96                    proto = baseProto; 
     97                }else{//for all others extend(do not overwrite) the final proto with the properties in the baseProto 
     98                    for(var key in baseProto){ 
     99                        if(proto[key] === undefined){ 
     100                            proto[key] = baseProto[key]; 
     101                        } 
     102                    } 
     103                } 
     104                //extend the new class' static interface 
     105                //todo: any props that should not be copied 
     106                for(var key in baseClass){ 
     107                    if((key != 'prototype') && (__class__[key] === undefined)){ 
     108                        __class__[key] = baseClass[key]; 
     109                    } 
     110                } 
     111            } 
     112        } 
     113        //make sure all jsolait objects have a id method 
     114        if(proto.__id__ === undefined){ 
     115            proto.__id__=function(){ 
     116                this.__id__ = '@' + (Class.__idcount__++); 
     117                return this.__id__; 
     118            }; 
     119        } 
     120        proto.__class__=__class__; 
     121 
     122        //run the class setup function provided as classScope 
     123        if(classScope.length-1 > baseProtos.length){ 
     124            var privId = '__priv__' + __class__.__id__; 
     125            classScope.apply(this,[proto, privId].concat(baseProtos)); 
     126        }else{ 
     127            classScope.apply(this,[proto].concat(baseProtos)); 
     128        } 
     129         
     130        //make sure the toString points to __str__, this will make overwriting __str__ after object construction impossible (todo ?) 
     131        //but will be faster than having toString call __str__, also overwriting methods unless they are ment to be overridden is not cool anyways. 
     132        proto.toString=proto.__str__; 
     133             
     134        //allthough a single constructor would suffice for generating normal objects, Arrays and callables, 
     135        //we use 3 different ones. This will minimize the code inside the constructor and therefore 
     136        //minimize object construction time 
     137        if(proto.__call__){ 
     138            //if the callable interface is implemented we need a class constructor 
     139            //which generates a function upon construction 
     140            var NewClass = function(calledBy){ 
     141                if(calledBy !== Class){ 
     142                    var rslt = function(){ 
     143                        return rslt.__call__.apply(rslt, arguments); 
     144                    }; 
     145                     
     146                    //this will only work for the current class but not create any priv objects for any base class  
     147                    var proto=arguments.callee.prototype; 
     148                    for(var n in proto){ 
     149                        rslt[n] = proto[n]; 
     150                    } 
     151                    rslt.constructor = proto.__class__; 
     152                    rslt.toString = proto.__str__; 
     153                    if(rslt.__init__){ 
     154                        rslt.__init__.apply(rslt, arguments); 
     155                    } 
     156                    return rslt; 
     157                } 
     158            }; 
     159        }else if(__class__.__isArray__){ 
     160            //Since we cannot inherit from Array directly we take the same approach as with the callable above 
     161            //and just have a constructor which creates an Array 
     162            var NewClass = function(calledBy){ 
     163                if(calledBy !== Class){ 
     164                    rslt=[]; 
     165 
     166                    var proto=arguments.callee.prototype; 
     167                    for(var n in proto){ 
     168                        rslt[n] = proto[n]; 
     169                    } 
     170                    rslt.constructor = proto.__class__; 
     171                    rslt.toString = proto.__str__; 
     172                    if(rslt.__init__){ 
     173                        rslt.__init__.apply(rslt, arguments); 
     174                    }else{//implement Array's default behavior 
     175                        if(arguments.length==1){ 
     176                            rslt.length=arguments[0]; 
     177                        }else{ 
     178                            for(var i=0;i<arguments.length;i++){ 
     179                                rslt.push(arguments[i]); 
     180                            } 
     181                        } 
     182                    } 
     183                    return rslt; 
     184                } 
     185            };  
     186        }else{ 
     187            //this is a 'normal' object constructor which does nothing but call the __init__ method 
     188            //unless it does not exsit or the constructor was used for prototyping 
     189            var NewClass = function(calledBy){ 
     190                if(calledBy !== Class){ 
     191                    if(this.__init__){ 
     192                        this.__init__.apply(this, arguments); 
     193                    } 
     194                } 
     195            }; 
     196        } 
     197 
     198        //reset the constructor for new objects to the actual constructor. 
     199        proto.constructor = NewClass; 
     200        proto.__class__= NewClass;//no, it is not needed, just like __str__ is not, but it is nicer than constructor 
     201             
     202        //this is where the inheritance realy happens 
     203        NewClass.prototype = proto; 
     204 
     205        //apply all the static fileds 
     206        for(var key in __class__){ 
     207            NewClass[key] = __class__[key]; 
     208        } 
     209        NewClass.toString=__class__.__str__; 
     210 
     211        return NewClass; 
     212    }; 
     213    Class.__idcount__=0; 
     214    Class.__str__=Class.toString = function(){return "[object Class]";}; 
     215    Class.__createProto__=function(){ throw "Can't use Class as a base class.";}; 
     216     
     217    jsolait.Class = Class; 
     218     
     219    jsolait.Exception=Class(function(publ){ 
     220        /** 
     221            Initializes a new Exception. 
     222            @param msg           The error message for the user. 
     223            @param trace=undefined  The error causing this Exception if available. 
     224        **/ 
     225        publ.__init__=function(msg, trace){ 
     226            this.name = this.constructor.__name__; 
     227            this.message = ''+msg; 
     228            this.trace = trace; 
     229        }; 
     230 
     231        publ.__str__=function(){ 
     232            return this.toTraceString(); 
     233        }; 
     234         
     235        /** 
     236            Returns the complete trace of the exception. 
     237            @param indent=0  The indention to use for each line. 
     238            @return The error trace. 
     239        **/ 
     240        publ.__str__=function(indent){ 
     241            indent = indent==null ? 0 : indent; 
     242 
     243            //todo:use  constructor.__name__? 
     244            var s="%s in %s:\n%s".format(this.name, this.module, this.message.indent(4)).indent(indent); 
     245            if(this.trace){ 
     246                if(this.trace.toTraceString){ 
     247                    s+=('\n\nbecause:\n'+ this.trace.toTraceString(indent + 4)); 
     248                }else{ 
     249                    s+=(this.trace +'\n').indent(indent+4); 
     250                } 
     251            } 
     252            return s; 
     253        }; 
     254 
     255        ///The name of the Exception. 
     256        publ.name;//todo is that needed? 
     257        ///The error message. 
     258        publ.message; 
     259        ///The module the Exception belongs to. 
     260        publ.module=jsolait; 
     261        ///The error which caused the Exception or undefined. 
     262        publ.trace; 
     263    }); 
     264     
     265    jsolait.ModuleClass=Class(function(publ){ 
     266        publ.__name__; 
     267        publ.__version__; 
     268        publ.__source__; 
     269        publ.__sourceURI__; 
     270        publ.Exception; 
     271         
     272        publ.__init__=function(name, source, sourceURI){ 
     273            this.__name__=name; 
     274            this.__version__=""; 
     275            this.__source__ = source; 
     276            this.__sourceURI__ = sourceURI; 
     277            this.Exception = Class(jsolait.Exception, new Function()); 
     278            this.Exception.prototype.module = this; 
     279        }; 
     280         
     281        publ.__str__=function(){ 
     282            //todo:SVN adaption 
     283            return "[module '%s' version: %s]".format(this.__name__, (this.__version__+'').replace(/\$Revision:\s(\d+) \$/, "Rev.$1")); 
     284        }; 
     285    }); 
    549286     
    550287    /** 
    551288        Creates an HTTP request object for retreiving files. 
    552289        @return HTTP request object. 
    553     *
    554     var getHTTP=function() { 
     290    **
     291    jsolait.getHTTPRequestObject=function() { 
    555292        var obj; 
    556293        try{ //to get the mozilla httprequest object 
     
    566303                        obj = new ActiveXObject("microsoft.XMLHTTP"); 
    567304                    }catch(e){ 
    568                         throw new mod.Exception("Unable to get an HTTP request object."); 
     305                        throw new jsolait.Exception("Unable to get an HTTP request object."); 
    569306                    } 
    570307                } 
     
    573310        return obj; 
    574311    }; 
    575  
    576     /** 
    577         Retrieves a file given its URL. 
    578         @param uri             The uri to load. 
    579         @param headers=[]  The headers to use. 
    580         @return                 The content of the file. 
    581     */ 
    582     mod.loadURI=function(uri, headers) { 
    583         headers = (headers !== undefined) ? headers : []; 
    584         try{ 
    585             var xmlhttp = getHTTP(); 
    586             xmlhttp.open("GET", uri, false); 
    587             for(var i=0;i< headers.length;i++){ 
    588                 xmlhttp.setRequestHeader(headers[i][0], headers[i][1]); 
    589             } 
    590             xmlhttp.send(""); 
    591         }catch(e){ 
    592             throw new mod.LoadURIFailed(uri, e); 
    593         } 
    594         //todo: the status checking needs testing 
    595         if(xmlhttp.status == 200 || xmlhttp.status == 0 || xmlhttp.status == null || xmlhttp.status == 304){ 
    596             var s= new String(xmlhttp.responseText); 
    597             s.__sourceURI__ = uri; 
    598             return s; 
    599         }else{ 
    600              throw new mod.LoadURIFailed(uri,new mod.Exception("Server did not respond with 200")); 
    601         } 
    602     }; 
    603  
     312         
    604313    /** 
    605314        Thrown when a file could not be loaded. 
    606315    **/ 
    607     mod.LoadURIFailed=Class(mod.Exception, function(publ, priv,supr){ 
     316    jsolait.LoadURIFailed=Class(jsolait.Exception, function(publ, priv,supr){ 
    608317        /** 
    609318            Initializes a new LoadURIFailed Exception. 
     
    619328        publ.sourceURI; 
    620329    }); 
    621  
    622  
    623      /** 
    624        Imports a module given its name(someModule.someSubModule). 
    625        A module's file location is determined by treating each module name as a directory. 
    626        Only the last one is assumed to point to a file. 
    627        If the module's URL is not known (i.e the module name was not found in jsolait.knownModuleURIs) 
    628        then it will be searched using all URIs found in jsolait.moduleSearchURIs. 
    629        @param name   The name of the module to load. 
    630        @return           The module object. 
    631     */ 
    632     mod.__imprt__ = function(name){ 
    633  
    634         if(mod.modules[name]){ //module already loaded 
    635             return mod.modules[name]; 
    636         }else{ 
    637             var src,modPath; 
    638              
    639             var searchURIs = []; 
    640              
    641             if(mod.knownModuleURIs[name] != undefined){ 
    642                 searchURIs.push(mod.knownModuleURIs[name].format(mod)); 
    643             }else{ 
    644                 name = name.split('.'); 
    645                 if(name.length>1){ 
    646                     if(mod.knownModuleURIs[name[0]] != undefined){ 
    647                         var uri = mod.knownModuleURIs[name[0]].format(mod); 
    648                         searchURIs.push("%s/%s.js".format(uri, name.slice(1).join('/'))); 
    649                     } 
    650                     searchURIs.push("%s/%s.js".format(mod.packagesURI.format(mod),name.join('/'))); 
    651                 } 
    652                  
    653                 for(var i=0;i<mod.moduleSearchURIs.length; i++){ 
    654                     searchURIs.push("%s/%s.js".format(mod.moduleSearchURIs[i].format(mod), name.join("/"))); 
    655                 } 
    656                 name =  name.join("."); 
    657             } 
    658              
    659             var failedURIs=[]; 
    660             for(var i=0;i<searchURIs.length;i++){ 
    661                 try{ 
    662                     src = mod.loadURI(searchURIs[i]); 
    663                     break; 
    664                 }catch(e){ 
    665                     failedURIs.push(e.sourceURI); 
    666                 } 
    667             } 
    668              
    669             if(src == null){ 
    670                 throw new mod.ImportFailed(name, failedURIs); 
    671             }else{ 
    672                 try{//interpret the script 
    673                     var srcURI = src.__sourceURI__; 
    674                     src = 'Module.currentURI="%s";\n%s\nModule.currentURI=null;\n'.format(src.__sourceURI__.replace(/\\/g, '\\\\'), src); 
    675                     var f=new Function("",src); 
    676                     f(); 
    677                 }catch(e){ 
    678                     throw new mod.ImportFailed(name, [srcURI], e); 
    679                 } 
    680                  
    681                 if(mod.modules[name] != null){ 
    682                     return mod.modules[name]; 
    683                 }else{ 
    684                     throw new mod.ImportFailed(name, [srcURI], new mod.Exception("Module did not register itself and cannot be imported. " + name)); 
    685                 } 
    686             } 
    687         } 
    688     }; 
    689  
    690  
     330     
     331    /** 
     332        Retrieves data given its URI. 
     333        @param uri             The uri to load. 
     334        @param headers=[]  The headers to use. 
     335        @return                 The content of the file. 
     336    **/ 
     337    jsolait.loadURI=function(uri, headers) { 
     338        headers = (headers !== undefined) ? headers : []; 
     339        try{ 
     340            var xmlhttp = jsolait.getHTTPRequestObject(); 
     341            xmlhttp.open("GET", uri, false); 
     342            for(var i=0;i< headers.length;i++){ 
     343                xmlhttp.setRequestHeader(headers[i][0], headers[i][1]); 
     344            } 
     345            xmlhttp.send(""); 
     346        }catch(e){ 
     347            throw new jsolait.LoadURIFailed(uri, e); 
     348        } 
     349        //todo: the status checking needs testing 
     350        if(xmlhttp.status == 200 || xmlhttp.status == 0 || xmlhttp.status == null || xmlhttp.status == 304){ 
     351            var s= str(xmlhttp.responseText); 
     352            return s; 
     353        }else{ 
     354             throw new jsolait.LoadURIFailed(uri, new jsolait.Exception("Server did not respond with status code 200 but with: " + xmlhttp.status)); 
     355        } 
     356    }; 
     357         
    691358    /** 
    692359        Thrown when a module could not be found. 
    693360    **/ 
    694     mod.ImportFailed=Class(mod.Exception, function(publ, supr){ 
     361    jsolait.LoadModuleFailed=Class(jsolait.Exception, function(publ, supr){ 
    695362        /** 
    696             Initializes a new ImportFailed Exception. 
     363            Initializes a new LoadModuleFailed Exception. 
    697364