Changeset 291

Show
Ignore:
Timestamp:
09/18/07 15:08:01 (6 years ago)
Author:
robert
Message:
  • switched to h2 (http://www.h2database.com) instead of hsqldb (mainly because of functionality not available in hsqldb, and the fact that h2 provides a nice database admin interface)
  • changes signature and functionality of jala.db.Server because the h2 tcp server works differently (eg. only disk-based databases are supported, but without the limit to 10 of hsqldb)
  • added optional username and password arguments to getUrl, getProperties and getConnection of Server, RamDatabase? and FileDatabase?. This makes it possible to use different credentials
  • it's now possible to dump a database as sql-script into a file by calling dump()
  • added new methods remove(), backup() and restore() to FileDatabase?
Files:
1 modified

Legend:

Unmodified
Added
Removed
  • jala/trunk/code/Database.js

    r234 r291  
    5050/** 
    5151 * Returns a new Server instance. 
    52  * @class Instances of this class represent a HSQLDB database server 
    53  * hosting up to 10 separate databases, which are accessible via network. 
    54  * <br /><strong>Important:</strong> You need the hsqldb.jar in lib/ext 
     52 * @class Instances of this class represent a H2 database listener that 
     53 * allows multiple databases to be accessed via tcp. 
     54 * <br /><strong>Important:</strong> You need the h2.jar in directory "lib/ext" 
    5555 * of your helma installation for this library to work, which you can get 
    56  * at http://hsqldb.org/. 
    57  * @param {String|Number} address Either the IP address or the port number or a combination 
    58  * of both in the form "ip:port". By default the IP address is "127.0.0.1" (aka localhost) 
    59  * and the port is 9001. 
     56 * at http://www.h2database.com/. 
     57 * @param {helma.File} baseDir The directory where the database files 
     58 * are located or should be stored 
     59 * @param {Number} port The port to listen on (defaults to 9001) 
     60 * @param {Boolean} createOnDemand If true this server will create non-existing 
     61 * databases on-the-fly, if false it only accepts connections to already 
     62 * existing databases in the given base directory 
     63 * @param {Boolean} makePublic If true this database is reachable from outside, 
     64 * if false it's only reachable from localhost 
     65 * @param {Boolean} useSsl If true SSL will be used to encrypt the connection 
    6066 * @returns A newly created Server instance 
    6167 * @constructor 
    6268 */ 
    63 jala.db.Server = function(address) { 
    64  
    65    /** 
    66     * Private variable containing the hsqldb server instance 
    67     * @type Packages.org.hsqldb.Server 
     69jala.db.Server = function(baseDir, port) { 
     70 
     71   /** 
     72    * Private variable containing the h2 server instance 
     73    * @type org.h2.tools.Server 
    6874    * @private 
    6975    */ 
    70    var server = new Packages.org.hsqldb.Server(); 
    71  
    72    /** 
    73     * Private array containing the databases within this server. 
    74     * The index position of a database in this array corresponds 
    75     * to the index position within the wrapped server. 
     76   var server = null; 
     77 
     78   /** 
     79    * An object containing configuration properties used when creating 
     80    * the server instance 
    7681    * @private 
    7782    */ 
    78    var databases = []; 
    79  
    80    /** 
    81     * Map containing the names of databases pointing 
    82     * to the index of the database within the server 
    83     * @private 
    84     */ 
    85    var names = {}; 
     83   var config = { 
     84      "baseDir": baseDir.getAbsolutePath(), 
     85      "tcpPort": port || 9092, 
     86      "tcpSSL": false, 
     87      "ifExists": true, 
     88      "tcpAllowOthers": false, 
     89      "log": false 
     90   }; 
    8691 
    8792   /** 
    8893    * Returns the wrapped database server instance 
    8994    * @returns The wrapped database server 
    90     * @type org.hsqldb.Server 
     95    * @type org.h2.tools.Server 
    9196    * @private 
    9297    */ 
     
    96101 
    97102   /** 
    98     * Returns the database with the given name. 
    99     * @param {String} name The name of the database to return 
    100     * @returns The database with the given name 
    101     * @type jala.db.RamDatabase 
     103    * Returns the directory used by this server instance 
     104    * @returns The directory where the databases used by this 
     105    * server are located in 
     106    * @type helma.File 
     107    */ 
     108   this.getDirectory = function() { 
     109      return baseDir; 
     110   }; 
     111 
     112   /** 
     113    * Returns the port this server listens on 
     114    * @returns The port this server listens on 
     115    * @type Number 
     116    */ 
     117   this.getPort = function() { 
     118      return config.tcpPort; 
     119   }; 
     120 
     121   /** 
     122    * Returns the config of this server 
     123    * @returns The config of this server 
    102124    * @private 
    103125    */ 
    104    this.getDatabase = function(name) { 
    105       var dbIdx; 
    106       if ((dbIdx = names[name]) != null) { 
    107          return databases[dbIdx]; 
    108       } 
    109       return null; 
    110    }; 
    111  
    112    /** 
    113     * Returns the map containing the database names registered 
    114     * within this server instance. 
    115     * @returns A map containing the database names as properties which 
    116     * value is the index position of the database within this server 
    117     * @type Object 
    118     * @private 
    119     */ 
    120    this.getDatabaseMap = function() { 
    121       return names; 
    122    }; 
    123  
    124    /** 
    125     * Returns an array containing all databases within this server. 
    126     * @returns All databases within this server 
    127     * @type Array 
    128     * @private 
    129     */ 
    130    this.getDatabases = function() { 
    131       return databases; 
    132    }; 
    133  
    134    /** 
    135     * Main constructor body 
    136     */ 
    137    var ip = "127.0.0.1"; 
    138    var port = 9001; 
    139    if (address != null) { 
    140       if (address.indexOf(":") > -1) { 
    141          ip = address.substring(0, address.indexOf(":")); 
    142          port = parseInt(address.substring(address.indexOf(":") + 1), 10); 
    143       } else if (!isNaN(address)) { 
    144          port = parseInt(address, 10); 
    145       } 
    146    } 
    147    // set the IP address and the port this server should listen on 
    148    server.setAddress(ip); 
    149    server.setPort(port); 
    150    app.logger.info("Jala : created instance listening on " + ip + ":" + port); 
     126   this.getConfig = function() { 
     127      return config; 
     128   }; 
     129 
     130   /** 
     131    * Starts the database server. 
     132    * @returns True in case the server started successfully, false otherwise 
     133    * @type Boolean 
     134    */ 
     135   this.start = function() { 
     136      if (server != null && server.isRunning()) { 
     137         throw "jala.db.Server: already listening on port " + this.getPort(); 
     138      } 
     139      // convert properties into an array 
     140      var config = this.getConfig(); 
     141      var args = []; 
     142      for (var propName in config) { 
     143         args.push("-" + propName); 
     144         args.push(config[propName].toString()); 
     145      } 
     146      // create the server instance 
     147      server = Packages.org.h2.tools.Server.createTcpServer(args); 
     148      try { 
     149         server.start(); 
     150      } catch (e) { 
     151         app.logger.error("jala.db.Server: unable to start server, reason: " + e); 
     152         return false; 
     153      } 
     154      app.logger.info("jala.db.Server: listening on localhost:" + this.getPort()); 
     155      return true; 
     156   }; 
     157 
     158 
    151159   return this; 
    152160}; 
     
    158166 
    159167/** 
    160  * Starts the database server. This should be called after all databases 
    161  * have been added. 
    162  * @see #addDatabase 
    163  */ 
    164 jala.db.Server.prototype.start = function() { 
    165    var server = this.getServer(); 
    166    server.setLogWriter(null); 
    167    server.setErrWriter(null); 
    168    server.start(); 
    169    return; 
    170 }; 
    171  
    172 /** 
    173168 * Stops the database server. 
     169 * @returns True if stopping the server was successful, false otherwise 
     170 * @type Boolean 
    174171 */ 
    175172jala.db.Server.prototype.stop = function() { 
    176    var server = this.getServer(); 
    177    server.stop(); 
    178    return; 
     173   try { 
     174      this.getServer().stop(); 
     175      app.logger.info("jala.db.Server: stopped listening on localhost:" + 
     176                      this.getPort()); 
     177   } catch (e) { 
     178      app.logger.error("jala.db.Server: Unable to stop, reason: " + e); 
     179      return false; 
     180   } 
     181   return true; 
    179182}; 
    180183 
     
    185188 */ 
    186189jala.db.Server.prototype.isRunning = function() { 
    187    return this.getServer().getState() == Packages.org.hsqldb.ServerConstants.SERVER_STATE_ONLINE; 
    188 }; 
    189  
    190 /** 
    191  * Adds a database to this server. 
    192  * @param {jala.db.RamDatabase} db The database to add 
    193  * @param {Object} props An optional parameter object containing database 
    194  * properties 
    195  */ 
    196 jala.db.Server.prototype.addDatabase = function(db, props) { 
    197    if (!(db instanceof jala.db.RamDatabase)) { 
    198       throw "jala.db.Server: Invalid argument to addDatabase(): " + db; 
    199    } 
    200    var name = db.getName(); 
    201    var map = this.getDatabaseMap(); 
    202    if (map[name] != null) { 
    203       throw "jala.db.Server: There is already a database registered with the name '" + 
    204              name + "'"; 
    205    } 
    206    var server = this.getServer(); 
    207    var databases = this.getDatabases(); 
    208    var dbIdx = databases.length; 
    209    var dbPath = db.getDatabasePath(); 
    210    dbPath += ";sql.enforce_strict_size=true"; 
    211    if (props != null) { 
    212       dbPath += jala.db.getPropertyString(props); 
    213    } 
    214    this.getDatabaseMap()[name] = dbIdx; 
    215    this.getDatabases()[dbIdx] = db; 
    216    // add the database to the server 
    217    server.setDatabaseName(dbIdx, name); 
    218    server.setDatabasePath(dbIdx, dbPath); 
     190   return this.getServer().isRunning(); 
     191}; 
     192 
     193/** 
     194 * Toggles the use of Ssl encryption within this server. This should be set 
     195 * before starting the server. 
     196 * @param {Boolean} bool If true SSL encryption will be used, false 
     197 * otherwise. If no argument is given, this method returns the 
     198 * current setting. 
     199 * @returns The current setting if no argument is given, or void 
     200 * @type Boolean 
     201 */ 
     202jala.db.Server.prototype.useSsl = function(bool) { 
     203   var config = this.getConfig(); 
     204   if (bool != null) { 
     205      config.tcpSSL = (bool === true); 
     206   } else { 
     207      return config.tcpSSL; 
     208   } 
    219209   return; 
    220210}; 
    221211 
    222212/** 
    223  * Returns the JDBC Url to use for connections to the 
    224  * specified database. 
     213 * If called with boolean true as argument, this server creates databases 
     214 * on-the-fly, otherwise it only accepts connections to already existing 
     215 * databases. This should be set before starting the server. 
     216 * @param {Boolean} bool If true this server creates non-existing databases 
     217 * on demand, if false it only allows connections to existing databases. 
     218 * If no argument is given, this method returns the current setting. 
     219 * @returns The current setting if no argument is given, or void 
     220 * @type Boolean 
     221 */ 
     222jala.db.Server.prototype.createOnDemand = function(bool) { 
     223   var config = this.getConfig(); 
     224   if (bool != null) { 
     225      config.ifExists = (bool === false); 
     226   } else { 
     227      return !config.ifExists; 
     228   } 
     229   return; 
     230}; 
     231 
     232/** 
     233 * If called with boolean true as argument, this server accepts connections 
     234 * from outside localhost. This should be set before starting the server. 
     235 * @param {Boolean} bool If true this server accepts connections from outside 
     236 * localhost. If no argument is given, this method returns the current setting. 
     237 * @returns The current setting if no argument is given, or void 
     238 * @type Boolean 
     239 */ 
     240jala.db.Server.prototype.isPublic = function(bool) { 
     241   var config = this.getConfig(); 
     242   if (bool != null) { 
     243      config.tcpAllowOthers = (bool === true); 
     244   } else { 
     245      return config.tcpAllowOthers; 
     246   } 
     247   return; 
     248}; 
     249 
     250/** 
     251 * Returns the JDBC Url to use for connections to a given database. 
    225252 * @param {String} name An optional name of a database running 
    226253 * @param {Object} props Optional connection properties to add 
     
    230257 */ 
    231258jala.db.Server.prototype.getUrl = function(name, props) { 
    232    if (!this.getDatabase(name)) { 
    233       throw "jala.db.Server: database '" + name + "' doesn't exist"; 
    234    } 
    235259   res.push(); 
    236    res.write("jdbc:hsqldb:hsql://localhost:"); 
    237    res.write(this.getServer().getPort()); 
     260   res.write("jdbc:h2:"); 
     261   res.write(this.useSsl() ? "ssl" : "tcp"); 
     262   res.write("://localhost:"); 
     263   res.write(this.getPort()); 
    238264   res.write("/"); 
    239    if (name != null) { 
    240       res.write(name); 
    241    } 
     265   res.write(name); 
    242266   res.write(jala.db.getPropertyString(props)) 
    243267   return res.pop(); 
     
    248272 * of the database with the given name. 
    249273 * @param {String} name The name of the database 
     274 * @param {String} username Optional username to use for this connection 
     275 * @param {String} password Optional password to use for this connection 
    250276 * @param {Object} props An optional parameter object containing 
    251277 * connection properties to add to the connection Url. 
     
    253279 * @type helma.util.ResourceProperties 
    254280 */ 
    255 jala.db.Server.prototype.getProperties = function(name, props) { 
    256    if (!this.getDatabase(name)) { 
    257       throw "jala.db.Server: database '" + name + "' doesn't exist"; 
    258    } 
     281jala.db.Server.prototype.getProperties = function(name, username, password, props) { 
    259282   var rp = new Packages.helma.util.ResourceProperties(); 
    260283   rp.put(name + ".url", this.getUrl(name, props)); 
    261    rp.put(name + ".driver", "org.hsqldb.jdbcDriver"); 
    262    rp.put(name + ".user", "sa"); 
    263    rp.put(name + ".password", ""); 
     284   rp.put(name + ".driver", "org.h2.Driver"); 
     285   rp.put(name + ".user", username || "sa"); 
     286   rp.put(name + ".password", password || ""); 
    264287   return rp; 
    265288}; 
     
    269292 * @param {String} name The name of the database running 
    270293 * within this server 
     294 * @param {String} username Optional username to use for this connection 
     295 * @param {String} password Optional password to use for this connection 
    271296 * @param {Object} props An optional parameter object 
    272297 * containing connection properties to add to the connection Url. 
     
    274299 * @type helma.Database 
    275300 */ 
    276 jala.db.Server.prototype.getConnection = function(name, props) { 
    277    var rp = this.getProperties(name, props); 
     301jala.db.Server.prototype.getConnection = function(name, username, password, props) { 
     302   var rp = this.getProperties(name, username, password, props); 
    278303   var dbSource = new Packages.helma.objectmodel.db.DbSource(name, rp); 
    279304   return new helma.Database(dbSource); 
     
    375400 * Returns a newly created RamDatabase instance. 
    376401 * @class Instances of this class represent an in-memory sql database. 
    377  * <br /><strong>Important:</strong> You need the hsqldb.jar in lib/ext 
     402 * <br /><strong>Important:</strong> You need the h2.jar in directory "lib/ext" 
    378403 * of your helma installation for this library to work, which you can get 
    379  * at http://hsqldb.org/. 
    380  * @param {String} name The name of the database 
     404 * at http://www.h2database.com/. 
     405 * @param {String} name The name of the database. If not given a private 
     406 * un-named database is created, that can only be accessed through this instance 
     407 * of jala.db.RamDatabase 
     408 * @param {String} username Optional username (defaults to "sa"). This username 
     409 * is used when creating the database, so the same should be used when 
     410 * creating subsequent instances of jala.db.RamDatabase pointing to a named 
     411 * database. 
     412 * @param {String} password Optional password (defaults to ""). 
    381413 * @returns A newly created instance of RamDatabase 
    382414 * @constructor 
    383415 */ 
    384 jala.db.RamDatabase = function(name) { 
     416jala.db.RamDatabase = function(name, username, password) { 
    385417 
    386418   /** 
     
    392424      return name; 
    393425   }; 
     426 
     427   /** 
     428    * Returns the username of this database 
     429    * @returns The username of this database 
     430    * @type String 
     431    */ 
     432   this.getUsername = function() { 
     433      return username; 
     434   }; 
     435    
     436   /** 
     437    * Returns the password of this database 
     438    * @returns The password of this database 
     439    * @type String 
     440    */ 
     441   this.getPassword = function() { 
     442      return password; 
     443   }; 
     444 
     445   /** 
     446    * Main constructor body 
     447    */ 
     448   if (!username) { 
     449      username = "sa"; 
     450   } 
     451   if (!password) { 
     452      password = ""; 
     453   } 
    394454 
    395455   return; 
     
    408468 */ 
    409469jala.db.RamDatabase.prototype.getUrl = function(props) { 
    410    var url = "jdbc:hsqldb:" + this.getDatabasePath(); 
     470   var url = "jdbc:h2:" + this.getDatabasePath(); 
    411471   if (props != null) { 
    412472      url += jala.db.getPropertyString(props); 
     
    438498   var rp = new Packages.helma.util.ResourceProperties(); 
    439499   rp.put(name + ".url", this.getUrl(props)); 
    440    rp.put(name + ".driver", "org.hsqldb.jdbcDriver"); 
    441    rp.put(name + ".user", "sa"); 
    442    rp.put(name + ".password", ""); 
     500   rp.put(name + ".driver", "org.h2.Driver"); 
     501   rp.put(name + ".user", this.getUsername()); 
     502   rp.put(name + ".password", this.getPassword()); 
    443503   return rp; 
    444504}; 
     
    710770 * Runs the script file passed as argument in the context of this database. 
    711771 * Use this method to eg. create and/or populate a database. 
    712  * @param {helma.File} file The script file to run. 
    713  */ 
    714 jala.db.RamDatabase.prototype.runScript = function(file) { 
     772 * @param {helma.File} file The script file to run 
     773 * @param {Object} props Optional object containing connection properties 
     774 * @param {String} charset Optional character set to use (defaults to "UTF-8") 
     775 * @param {Boolean} continueOnError Optional flag indicating whether to continue 
     776 * on error or not (defaults to false) 
     777 * @returns True in case the script was executed successfully, false otherwise 
     778 * @type Boolean 
     779 */ 
     780jala.db.RamDatabase.prototype.runScript = function(file, props, charset, continueOnError) { 
    715781   try { 
    716       var sqlFile = new Packages.org.hsqldb.util.SqlFile(new java.io.File(file), false, new java.util.HashMap()); 
    717       var conn = this.getConnection().getConnection(); 
    718       sqlFile.execute(conn, false); 
    719       app.logger.info("Jala Database: successfully executed SQL script '" + file.getAbsolutePath() + "'"); 
    720       return true; 
     782      Packages.org.h2.tools.RunScript.execute( 
     783         this.getUrl(props), 
     784         "sa", 
     785         "", 
     786         file.getAbsolutePath(), 
     787         charset || "UTF-8", 
     788         continueOnError === true 
     789      ); 
     790      app.logger.info("jala.db: successfully executed SQL script '" + 
     791                      file.getAbsolutePath() + "'"); 
    721792   } catch (e) { 
    722       app.logger.error("Jala Database: executing SQL script failed, reason: " + e); 
     793      app.logger.error("jala.db: executing SQL script failed, reason: " + e); 
    723794      return false; 
    724    } finally { 
    725       if (conn != null) { 
    726          conn.close(); 
    727       } 
    728    } 
    729 }; 
    730  
     795   } 
     796   return true; 
     797}; 
     798 
     799/** 
     800 * Dumps the database schema and data into a file 
     801 * @param {helma.File} file The file where the database dump will be 
     802 * @param {Object} props Optional object containing connection properties 
     803 * @returns True in case the database was successfully dumped, false otherwise 
     804 * @type Boolean 
     805 */ 
     806jala.db.RamDatabase.prototype.dump = function(file, props) { 
     807   try { 
     808      Packages.org.h2.tools.Script.execute(this.getUrl(props), 
     809            "sa", "", file.getAbsolutePath()); 
     810   } catch (e) { 
     811      app.logger.error("jala.db: Unable to dump database to '" + file.getAbsolutePath() + 
     812            ", reason: " + e.toString()); 
     813      return false; 
     814   } 
     815   return true; 
     816}; 
    731817 
    732818 
     
    739825 * Returns a newly created instance of FileDatabase. 
    740826 * @class Instances of this class represent a file based in-process database 
    741  * <br /><strong>Important:</strong> You need the hsqldb.jar in lib/ext 
     827 * <br /><strong>Important:</strong> You need the h2.jar in directory "lib/ext" 
    742828 * of your helma installation for this library to work, which you can get 
    743  * at http://hsqldb.org/. 
    744  * @param {String} name The name of the database 
     829 * at http://www.h2database.com/. 
     830 * @param {String} name The name of the database. This name is used as 
     831 * prefix for all database files 
    745832 * @param {helma.File} directory The directory where the database files 
    746833 * should be stored in. 
     834 * @param {String} username Optional username (defaults to "sa"). This username 
     835 * is used when creating the database, so the same should be used when 
     836 * creating subsequent instances of jala.db.FileDatabase pointing to the 
     837 * same database 
     838 * @param {String} password Optional password (defaults to ""). 
    747839 * @returns A newly created FileDatabase instance 
    748840 * @constructor 
    749841 */ 
    750 jala.db.FileDatabase = function(name, directory) { 
    751  
    752    /** 
    753     * Returns the name of the database 
     842jala.db.FileDatabase = function(name, directory, username, password) { 
     843 
     844   /** 
     845    * Returns the name of the database. This name is used as prefix 
     846    * for all files of this database in the specified directory 
    754847    * @returns The name of the database 
    755848    * @type String 
     
    761854   /** 
    762855    * Returns the directory where the database files are stored. 
    763     * @returns The directory where the database is stored. 
     856    * @returns The directory where this database is stored. 
    764857    * @type helma.File 
    765858    */ 
     
    768861   }; 
    769862 
     863   /** 
     864    * Returns the username of this database 
     865    * @returns The username of this database 
     866    * @type String 
     867    */ 
     868   this.getUsername = function() { 
     869      return username; 
     870   }; 
     871    
     872   /** 
     873    * Returns the password of this database 
     874    * @returns The password of this database 
     875    * @type String 
     876    */ 
     877   this.getPassword = function() { 
     878      return password; 
     879   }; 
     880 
     881   if (!name || typeof(name) != "string" || 
     882             !directory || !(directory instanceof helma.File)) { 
     883      throw "jala.db.FileDatabase: Missing or invalid arguments" 
     884   } else if (!directory.exists()) { 
     885      throw "jala.db.FileDatabase: directory '" + directory + "' does not exist"; 
     886   } 
     887 
    770888   return this; 
    771889}; 
     
    775893/** @ignore */ 
    776894jala.db.FileDatabase.prototype.toString = function() { 
    777    return "[Jala FileDatabase " + this.getName() + 
    778           " (" + this.getDirectory().getAbsolutePath() + ")]"; 
     895   return "[Jala FileDatabase '" + this.getName() + "' in " 
     896          + this.getDirectory().getAbsolutePath() + "]"; 
    779897}; 
    780898 
     
    790908   return "file:" + directory.getAbsolutePath(); 
    791909}; 
     910 
     911/** 
     912 * Deletes all files of this database on disk. Note that this also 
     913 * closes the database before removing it. 
     914 * @returns True in case the database was removed successfully, false otherwise 
     915 * @type Boolean 
     916 */ 
     917jala.db.FileDatabase.prototype.remove = function() { 
     918   var directory = this.getDirectory(); 
     919   try { 
     920      // shut down the database 
     921      this.shutdown(); 
     922      Packages.org.h2.tools.DeleteDbFiles.execute( 
     923         directory.getAbsolutePath(), 
     924         this.getName(), 
     925         false 
     926      ); 
     927   } catch(e) { 
     928      app.logger.error("jala.db: Unable to delete database in " + 
     929            directory.getAbsolutePath() + ", reason: " + e); 
     930      return false; 
     931   } 
     932   return true; 
     933}; 
     934 
     935/** 
     936 * Creates a backup of this database, using the file passed as argument. The 
     937 * result will be a zipped file containing the database files 
     938 * @param {helma.File} file The file to write the backup to 
     939 * @returns True if the database backup was created successfully, false otherwise 
     940 * @type Boolean 
     941 */ 
     942jala.db.FileDatabase.prototype.backup = function(file) { 
     943   try { 
     944      Packages.org.h2.tools.Backup.execute( 
     945         file.getAbsolutePath(), 
     946         this.getDirectory().getAbsolutePath(), 
     947         this.getName(), 
     948         false 
     949      ); 
     950   } catch (e) { 
     951      app.logger.error("jala.db: Unable to backup database to '" + 
     952                       file.getAbsolutePath() + ", reason: " + e); 
     953      return false; 
     954   } 
     955   return true; 
     956}; 
     957 
     958/** 
     959 * Restores this database using a backup on disk. 
     960 * @param {helma.File} backupFile The backup file to use for restore 
     961 * @returns True if the database was successfully restored, false otherwise 
     962 * @type Boolean 
     963 */ 
     964jala.db.FileDatabase.prototype.restore = function(backupFile) { 
     965   try { 
     966      Packages.org.h2.tools.Restore.execute( 
     967         backupFile.getAbsolutePath(), 
     968         this.getDirectory().getAbsolutePath(), 
     969         this.getName(), 
     970         false 
     971      ); 
     972   } catch (e) { 
     973      app.logger.error("jala.db: Unable to restore database using '" + 
     974                       backupFile.getAbsolutePath() + ", reason: " + e); 
     975      return false; 
     976   } 
     977   return true; 
     978};