1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.waarp.common.database.model;
21
22 import org.postgresql.util.PSQLException;
23 import org.waarp.common.database.DbAdmin;
24 import org.waarp.common.database.DbConstant;
25 import org.waarp.common.database.DbSession;
26 import org.waarp.common.database.exception.WaarpDatabaseNoConnectionException;
27 import org.waarp.common.database.exception.WaarpDatabaseSqlException;
28 import org.waarp.common.logging.WaarpLogger;
29 import org.waarp.common.logging.WaarpLoggerFactory;
30
31 import java.sql.Connection;
32 import java.sql.DriverManager;
33 import java.sql.ResultSet;
34 import java.sql.SQLException;
35 import java.sql.Statement;
36 import java.util.ConcurrentModificationException;
37
38
39
40
41 public abstract class DbModelAbstract implements DbModel {
42
43
44
45 public static final int MAX_BINARY = 255;
46
47
48
49 public static final int MAX_LONGVARCHAR = 12 * 1024;
50
51
52
53 public static final int MAX_KEY_VARCHAR = 255;
54
55
56
57 public static final int MAX_VARCHAR = 8096;
58 protected static DbTypeResolver dbTypeResolver;
59
60 public abstract static class DbTypeResolver {
61 public abstract String getType(int sqlType);
62
63 public String getCreateTable() {
64 return "CREATE TABLE ";
65 }
66
67 public String getPrimaryKey() {
68 return " PRIMARY KEY ";
69 }
70
71 public String getNotNull() {
72 return " NOT NULL ";
73 }
74
75 public String getCreateIndex() {
76 return "CREATE INDEX ";
77 }
78
79 public abstract DbType getDbType();
80 }
81
82 public DbTypeResolver getDbTypeResolver() {
83 return dbTypeResolver;
84 }
85
86
87
88
89 private static final WaarpLogger logger =
90 WaarpLoggerFactory.getLogger(DbModelAbstract.class);
91 private static final String CANNOT_CONNECT_TO_DATABASE =
92 "Cannot connect to database";
93
94
95
96
97
98
99
100
101 private void recreateSession(final DbSession dbSession)
102 throws WaarpDatabaseNoConnectionException {
103 DbAdmin admin = dbSession.getAdmin();
104 if (admin == null) {
105 if (dbSession.isAutoCommit()) {
106 admin = DbConstant.admin;
107 } else {
108 admin = DbConstant.noCommitAdmin;
109 }
110 }
111 final DbSession newdbSession;
112 newdbSession = new DbSession(admin, dbSession.isReadOnly());
113 try {
114 if (dbSession.getConn() != null) {
115 dbSession.getConn().close();
116 }
117 } catch (final SQLException ignored) {
118
119 } catch (final ConcurrentModificationException ignored) {
120
121 }
122 dbSession.setConn(newdbSession.getConn());
123 DbAdmin.addConnection(dbSession.getInternalId(), dbSession);
124 DbAdmin.removeConnection(newdbSession.getInternalId());
125 logger.warn("Database Connection lost: database connection reopened");
126 }
127
128
129
130
131
132
133 protected final void closeInternalConnection(final DbSession dbSession) {
134 try {
135 if (dbSession.getConn() != null) {
136 dbSession.getConn().close();
137 }
138 } catch (final SQLException ignored) {
139
140 } catch (final ConcurrentModificationException ignored) {
141
142 }
143 dbSession.setDisActive(true);
144 DbAdmin.removeConnection(dbSession.getInternalId());
145 }
146
147 @Override
148 public final void validConnection(final DbSession dbSession)
149 throws WaarpDatabaseNoConnectionException {
150
151 synchronized (this) {
152 if (dbSession.getConn() == null) {
153 throw new WaarpDatabaseNoConnectionException(
154 CANNOT_CONNECT_TO_DATABASE);
155 }
156 try {
157 if (!dbSession.getConn().isClosed() &&
158 !dbSession.getConn().isValid(DbConstant.VALIDTESTDURATION)) {
159
160 throw new SQLException(CANNOT_CONNECT_TO_DATABASE);
161 }
162 dbSession.setDisActive(false);
163 } catch (final SQLException e2) {
164 dbSession.setDisActive(true);
165
166 if (e2 instanceof PSQLException) {
167 validConnectionSelect(dbSession);
168 return;
169 }
170 if (subValidationConnection(dbSession, e2)) {
171 return;
172 }
173 closeInternalConnection(dbSession);
174 throw new WaarpDatabaseNoConnectionException(CANNOT_CONNECT_TO_DATABASE,
175 e2);
176 }
177 }
178 }
179
180 private boolean subValidationConnection(final DbSession dbSession,
181 final SQLException e2)
182 throws WaarpDatabaseNoConnectionException {
183 try {
184 try {
185 recreateSession(dbSession);
186 } catch (final WaarpDatabaseNoConnectionException e) {
187 closeInternalConnection(dbSession);
188 throw e;
189 }
190 try {
191 if (!dbSession.getConn().isValid(DbConstant.VALIDTESTDURATION)) {
192
193 closeInternalConnection(dbSession);
194 throw new WaarpDatabaseNoConnectionException(
195 CANNOT_CONNECT_TO_DATABASE, e2);
196 }
197 } catch (final SQLException e) {
198 closeInternalConnection(dbSession);
199 throw new WaarpDatabaseNoConnectionException(CANNOT_CONNECT_TO_DATABASE,
200 e);
201 }
202 dbSession.setDisActive(false);
203 dbSession.recreateLongTermPreparedStatements();
204 return true;
205 } catch (final WaarpDatabaseSqlException e1) {
206
207 }
208 return false;
209 }
210
211 protected final void validConnectionSelect(final DbSession dbSession)
212 throws WaarpDatabaseNoConnectionException {
213
214 synchronized (this) {
215 Statement stmt = null;
216 try {
217 stmt = dbSession.getConn().createStatement();
218 if (stmt.execute(validConnectionString())) {
219 ResultSet set = null;
220 try {
221 set = stmt.getResultSet();
222 if (!set.next()) {
223 closingStatement(stmt);
224
225 throw new SQLException(CANNOT_CONNECT_TO_DATABASE);
226 }
227 } finally {
228 if (set != null) {
229 set.close();
230 }
231 }
232 }
233 dbSession.setDisActive(false);
234 } catch (final SQLException e2) {
235 dbSession.setDisActive(true);
236 stmt = subValidConnectionSelect(dbSession, stmt);
237 if (stmt == null) {
238 return;
239 }
240 closeInternalConnection(dbSession);
241 throw new WaarpDatabaseNoConnectionException(CANNOT_CONNECT_TO_DATABASE,
242 e2);
243 } finally {
244 closingStatement(stmt);
245 }
246 }
247 }
248
249 private void closingStatement(final Statement stmt) {
250 try {
251 if (stmt != null) {
252 stmt.close();
253 }
254 } catch (final SQLException e) {
255
256 }
257 }
258
259 private Statement subValidConnectionSelect(final DbSession dbSession,
260 Statement stmt)
261 throws WaarpDatabaseNoConnectionException {
262 try {
263 try {
264 recreateSession(dbSession);
265 } catch (final WaarpDatabaseNoConnectionException e) {
266 closeInternalConnection(dbSession);
267 throw e;
268 }
269 closingStatement(stmt);
270 try {
271 stmt = dbSession.getConn().createStatement();
272 } catch (final SQLException e) {
273
274 closeInternalConnection(dbSession);
275 throw new WaarpDatabaseNoConnectionException(CANNOT_CONNECT_TO_DATABASE,
276 e);
277 }
278 try {
279 if (stmt.execute(validConnectionString())) {
280 ResultSet set = null;
281 try {
282 set = stmt.getResultSet();
283 if (!set.next()) {
284 closingStatement(stmt);
285 closeInternalConnection(dbSession);
286 throw new WaarpDatabaseNoConnectionException(
287 CANNOT_CONNECT_TO_DATABASE);
288 }
289 } finally {
290 if (set != null) {
291 set.close();
292 }
293 }
294 }
295 } catch (final SQLException e) {
296 closingStatement(stmt);
297 closeInternalConnection(dbSession);
298 throw new WaarpDatabaseNoConnectionException(CANNOT_CONNECT_TO_DATABASE,
299 e);
300 }
301 dbSession.setDisActive(false);
302 dbSession.recreateLongTermPreparedStatements();
303 closingStatement(stmt);
304 return null;
305 } catch (final WaarpDatabaseSqlException e1) {
306
307 }
308 return stmt;
309 }
310
311
312
313
314
315
316 protected abstract String validConnectionString();
317
318 @Override
319 public Connection getDbConnection(final String server, final String user,
320 final String passwd) throws SQLException {
321
322 return DriverManager.getConnection(server, user, passwd);
323 }
324
325 @Override
326 public void releaseResources() {
327 }
328
329 @Override
330 public int currentNumberOfPooledConnections() {
331 return DbAdmin.getNbConnection();
332 }
333
334 }