Mercurial Hosting > nabble
diff src/nabble/model/Db.java @ 0:7ecd1a4ef557
add content
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Thu, 21 Mar 2019 19:15:52 -0600 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/nabble/model/Db.java Thu Mar 21 19:15:52 2019 -0600 @@ -0,0 +1,164 @@ +/* + +Copyright (C) 2003 Franklin Schmidt <frank@gustos.com> + +*/ + +package nabble.model; + +import fschmidt.db.DbArcana; +import fschmidt.db.DbDatabase; +import fschmidt.db.DbFinder; +import fschmidt.db.util.WeakCacheMap; +import fschmidt.util.java.Computable; +import fschmidt.util.java.SimpleCache; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.HashMap; +import java.util.Map; + + +public final class Db { + private static final Logger logger = LoggerFactory.getLogger(Db.class); + static final String url = (String)Init.get("dbUrl"); + static final String user = (String)Init.get("dbUser"); + static final String password = (String)Init.get("dbPassword"); + private static final long idleTimeout = Init.get("idleTimeout",5*60*1000L); + + static final String completeUrl = url + "?user=" + user + "&password=" + password; + + private static final DbDatabase baseDb = DbFinder.getBaseDatabase(url,user,password); + private static final fschmidt.db.pool.Pool pool = new fschmidt.db.pool.Pool(); + static { + pool.setIdleTimeout(idleTimeout); + } + + private static final class NoUserException extends SQLException { + NoUserException(SQLException e) { + super(e); + } + } + + static Connection getNativeConnection() { + return pool.getNativeConnection(); + } + + static void checkUser(String user) { + try { + Connection con = baseDb.getConnection(); + Statement stmt = con.createStatement(); + try { + stmt.executeUpdate( + "set role " + user + ); + } catch(SQLException e) { + stmt.executeUpdate( + "create user " + user + " with password '" + password + "'" + ); + stmt.executeUpdate( + "set role " + user + ); + } + stmt.close(); + con.close(); + } catch(SQLException e) { + throw new RuntimeException("check user failed for: "+user,e); + } + } + + static class NoSchema extends RuntimeException { + private NoSchema(String msg) { + super(msg); + } + } + + private static void checkSchema(String schema) { + try { + Connection con = dbPostgres.getConnection(); + Statement stmt = con.createStatement(); + try { + stmt.executeQuery( + "select * from "+schema+".version" + ); + } catch(SQLException e) { + if( e.getMessage().contains("does not exist") ) + throw new NoSchema(schema); + throw e; + } finally { + stmt.close(); + con.close(); + } + } catch(SQLException e) { + throw new RuntimeException("check schema failed for: "+schema,e); + } + } + + static DbDatabase pooledDb(String user) { + return new fschmidt.db.pool.DbDatabaseImpl(baseDb,pool,user); + } + + private static DbDatabase getDb(String user) { + DbDatabase pooledDb = pooledDb(user); + DbDatabase db = new fschmidt.db.cache.DbDatabaseImpl(pooledDb); + if( !user.equals(Db.user) ) { + checkSchema(user); + try { + DbSiteUpdater.update(user,db); + } catch(UpdatingException e) { + throw e; + } catch(RuntimeException e) { + throw new RuntimeException("couldn't update db for: "+user,e); + } catch(SQLException e) { + throw new RuntimeException("couldn't update db for: "+user,e); + } + } + return db; + } + + private static final DbDatabase dbPostgres = getDb(user); + public static final DbArcana arcana = dbPostgres.arcana(); + + private static SimpleCache<String,DbDatabase> cache = new SimpleCache<String,DbDatabase>(new WeakCacheMap<String,DbDatabase>(), new Computable<String,DbDatabase>() { + public DbDatabase get(String user) { + return getDb(user); + } + }); + + static void uncache(String user) { + cache.remove(user); + } + + static DbDatabase db(String user) { + return cache.get(user); + } + + public static DbDatabase dbPostgres() { + return dbPostgres; + } + + public static DbDatabase dbGlobal() { + return db("global"); + } + + public static void clearCache() { + fschmidt.db.cache.DbDatabaseImpl.clearCache(); + } + + + public static void main(String[] args) throws Exception { + Connection con = dbPostgres.getConnection(); + Statement stmt = con.createStatement(); + for( String arg : args ) { + stmt.executeUpdate(arg); + } + stmt.close(); + con.close(); + } + + private Db() {} // never +}