0
|
1 /*
|
|
2
|
|
3 Copyright (C) 2003 Franklin Schmidt <frank@gustos.com>
|
|
4
|
|
5 */
|
|
6
|
|
7 package nabble.model;
|
|
8
|
|
9 import fschmidt.db.DbArcana;
|
|
10 import fschmidt.db.DbDatabase;
|
|
11 import fschmidt.db.DbFinder;
|
|
12 import fschmidt.db.util.WeakCacheMap;
|
|
13 import fschmidt.util.java.Computable;
|
|
14 import fschmidt.util.java.SimpleCache;
|
|
15 import org.slf4j.Logger;
|
|
16 import org.slf4j.LoggerFactory;
|
|
17
|
|
18 import java.sql.Connection;
|
|
19 import java.sql.PreparedStatement;
|
|
20 import java.sql.SQLException;
|
|
21 import java.sql.Statement;
|
|
22 import java.util.HashMap;
|
|
23 import java.util.Map;
|
|
24
|
|
25
|
|
26 public final class Db {
|
|
27 private static final Logger logger = LoggerFactory.getLogger(Db.class);
|
|
28 static final String url = (String)Init.get("dbUrl");
|
|
29 static final String user = (String)Init.get("dbUser");
|
|
30 static final String password = (String)Init.get("dbPassword");
|
|
31 private static final long idleTimeout = Init.get("idleTimeout",5*60*1000L);
|
|
32
|
|
33 static final String completeUrl = url + "?user=" + user + "&password=" + password;
|
|
34
|
|
35 private static final DbDatabase baseDb = DbFinder.getBaseDatabase(url,user,password);
|
|
36 private static final fschmidt.db.pool.Pool pool = new fschmidt.db.pool.Pool();
|
|
37 static {
|
|
38 pool.setIdleTimeout(idleTimeout);
|
|
39 }
|
|
40
|
|
41 private static final class NoUserException extends SQLException {
|
|
42 NoUserException(SQLException e) {
|
|
43 super(e);
|
|
44 }
|
|
45 }
|
|
46
|
|
47 static Connection getNativeConnection() {
|
|
48 return pool.getNativeConnection();
|
|
49 }
|
|
50
|
|
51 static void checkUser(String user) {
|
|
52 try {
|
|
53 Connection con = baseDb.getConnection();
|
|
54 Statement stmt = con.createStatement();
|
|
55 try {
|
|
56 stmt.executeUpdate(
|
|
57 "set role " + user
|
|
58 );
|
|
59 } catch(SQLException e) {
|
|
60 stmt.executeUpdate(
|
|
61 "create user " + user + " with password '" + password + "'"
|
|
62 );
|
|
63 stmt.executeUpdate(
|
|
64 "set role " + user
|
|
65 );
|
|
66 }
|
|
67 stmt.close();
|
|
68 con.close();
|
|
69 } catch(SQLException e) {
|
|
70 throw new RuntimeException("check user failed for: "+user,e);
|
|
71 }
|
|
72 }
|
|
73
|
|
74 static class NoSchema extends RuntimeException {
|
|
75 private NoSchema(String msg) {
|
|
76 super(msg);
|
|
77 }
|
|
78 }
|
|
79
|
|
80 private static void checkSchema(String schema) {
|
|
81 try {
|
|
82 Connection con = dbPostgres.getConnection();
|
|
83 Statement stmt = con.createStatement();
|
|
84 try {
|
|
85 stmt.executeQuery(
|
|
86 "select * from "+schema+".version"
|
|
87 );
|
|
88 } catch(SQLException e) {
|
|
89 if( e.getMessage().contains("does not exist") )
|
|
90 throw new NoSchema(schema);
|
|
91 throw e;
|
|
92 } finally {
|
|
93 stmt.close();
|
|
94 con.close();
|
|
95 }
|
|
96 } catch(SQLException e) {
|
|
97 throw new RuntimeException("check schema failed for: "+schema,e);
|
|
98 }
|
|
99 }
|
|
100
|
|
101 static DbDatabase pooledDb(String user) {
|
|
102 return new fschmidt.db.pool.DbDatabaseImpl(baseDb,pool,user);
|
|
103 }
|
|
104
|
|
105 private static DbDatabase getDb(String user) {
|
|
106 DbDatabase pooledDb = pooledDb(user);
|
|
107 DbDatabase db = new fschmidt.db.cache.DbDatabaseImpl(pooledDb);
|
|
108 if( !user.equals(Db.user) ) {
|
|
109 checkSchema(user);
|
|
110 try {
|
|
111 DbSiteUpdater.update(user,db);
|
|
112 } catch(UpdatingException e) {
|
|
113 throw e;
|
|
114 } catch(RuntimeException e) {
|
|
115 throw new RuntimeException("couldn't update db for: "+user,e);
|
|
116 } catch(SQLException e) {
|
|
117 throw new RuntimeException("couldn't update db for: "+user,e);
|
|
118 }
|
|
119 }
|
|
120 return db;
|
|
121 }
|
|
122
|
|
123 private static final DbDatabase dbPostgres = getDb(user);
|
|
124 public static final DbArcana arcana = dbPostgres.arcana();
|
|
125
|
|
126 private static SimpleCache<String,DbDatabase> cache = new SimpleCache<String,DbDatabase>(new WeakCacheMap<String,DbDatabase>(), new Computable<String,DbDatabase>() {
|
|
127 public DbDatabase get(String user) {
|
|
128 return getDb(user);
|
|
129 }
|
|
130 });
|
|
131
|
|
132 static void uncache(String user) {
|
|
133 cache.remove(user);
|
|
134 }
|
|
135
|
|
136 static DbDatabase db(String user) {
|
|
137 return cache.get(user);
|
|
138 }
|
|
139
|
|
140 public static DbDatabase dbPostgres() {
|
|
141 return dbPostgres;
|
|
142 }
|
|
143
|
|
144 public static DbDatabase dbGlobal() {
|
|
145 return db("global");
|
|
146 }
|
|
147
|
|
148 public static void clearCache() {
|
|
149 fschmidt.db.cache.DbDatabaseImpl.clearCache();
|
|
150 }
|
|
151
|
|
152
|
|
153 public static void main(String[] args) throws Exception {
|
|
154 Connection con = dbPostgres.getConnection();
|
|
155 Statement stmt = con.createStatement();
|
|
156 for( String arg : args ) {
|
|
157 stmt.executeUpdate(arg);
|
|
158 }
|
|
159 stmt.close();
|
|
160 con.close();
|
|
161 }
|
|
162
|
|
163 private Db() {} // never
|
|
164 }
|