001: /*
002: * @(#) SmartConnection 1.0 02/08/01
003: */
004:
005: package org.smartlib.pool.core;
006:
007: import java.sql.*;
008: import java.util.*;
009:
010: /**
011: * This class encapsulates a Connection.
012: * Dont expect me to document this class, if you want refer Sun's Documentation.
013: *
014: * @author Sachin Shekar Shetty
015: * @version 1.0, 02/08/01
016: */
017:
018: public class SmartConnection implements Connection, Close,
019: ConnectionMonitor {
020:
021: private Connection conn = null;
022: private long lastAccessedTime = 0;
023: private long connectionObtainedTime = 0;
024:
025: private ArrayList references;
026: private boolean autoClose = false;
027: private Debugger debug;
028:
029: private boolean isCurrentlyInTransaction;
030:
031: //Pool Ref to which this connection belongs
032: private Pool poolReference;
033:
034: private boolean isClosed = false;
035:
036: private boolean isForcedClosed = false;
037: private long forcedCloseTime = 0;
038:
039: private String owner;
040:
041: // default contructor , can only be used within the package
042: SmartConnection(Connection conn, Pool poolReference, String owner,
043: boolean autoClose) {
044:
045: if (conn == null)
046: throw new IllegalArgumentException(
047: "Connection Object is null/closed");
048: this .conn = conn;
049: this .poolReference = poolReference;
050: this .owner = owner;
051: lastAccessedTime = System.currentTimeMillis();
052: connectionObtainedTime = lastAccessedTime;
053: this .autoClose = autoClose;
054: if (autoClose)
055: references = new ArrayList();
056: debug = new Debugger("SmartConnection", true);
057:
058: }
059:
060: SmartConnection(Connection conn, Pool poolReference) {
061:
062: this (conn, poolReference, "N/A", false);
063:
064: }
065:
066: private void preProcess() throws SQLException {
067:
068: if (isForcedClosed)
069: throw new StaleConnectionException(
070: "SmartPool had withdrawn the connection since it was idle for more than the specified time. Connection withdrawn at "
071: + new java.util.Date(forcedCloseTime));
072: if (isClosed)
073: throw new SQLException("Connection already closed");
074: lastAccessedTime = System.currentTimeMillis();
075:
076: }
077:
078: public long getLastAccessedTime() {
079:
080: return lastAccessedTime;
081:
082: }
083:
084: void setLastAccessedTime() {
085:
086: lastAccessedTime = System.currentTimeMillis();
087:
088: }
089:
090: public boolean isCurrentlyInTransaction() {
091:
092: return isCurrentlyInTransaction;
093:
094: }
095:
096: public String getPoolName() {
097: return ((PoolMonitor) poolReference).getName();
098: }
099:
100: // default access , only accessible within the package
101: public long getConnectionObtainedTime() {
102:
103: return connectionObtainedTime;
104:
105: }
106:
107: public String getOwner() {
108:
109: return owner;
110:
111: }
112:
113: public Statement createStatement() throws SQLException {
114:
115: preProcess();
116: SmartStatement stmt = new SmartStatement(
117: conn.createStatement(), this );
118: if (autoClose)
119: references.add(stmt);
120: return stmt;
121:
122: }
123:
124: public PreparedStatement prepareStatement(String sql)
125: throws SQLException {
126:
127: preProcess();
128: SmartPreparedStatement pstmt = new SmartPreparedStatement(conn
129: .prepareStatement(sql), this );
130: if (autoClose)
131: references.add(pstmt);
132: return pstmt;
133:
134: }
135:
136: public CallableStatement prepareCall(String sql)
137: throws SQLException {
138:
139: preProcess();
140: SmartCallableStatement cstmt = new SmartCallableStatement(conn
141: .prepareCall(sql), this );
142: if (autoClose)
143: references.add(cstmt);
144: return cstmt;
145:
146: }
147:
148: public String nativeSQL(String sql) throws SQLException {
149:
150: preProcess();
151: return conn.nativeSQL(sql);
152:
153: }
154:
155: public void setAutoCommit(boolean autoCommit) throws SQLException {
156:
157: preProcess();
158: isCurrentlyInTransaction = autoCommit;
159: conn.setAutoCommit(autoCommit);
160:
161: }
162:
163: public boolean getAutoCommit() throws SQLException {
164:
165: preProcess();
166: return conn.getAutoCommit();
167:
168: }
169:
170: public void commit() throws SQLException {
171:
172: preProcess();
173: conn.commit();
174:
175: }
176:
177: public void rollback() throws SQLException {
178:
179: preProcess();
180: conn.rollback();
181:
182: }
183:
184: /**
185: * This method is called when the connection is idle for more than
186: * the specified time in max-conection-idle-time in configuration.
187: * The PollThread calls this method to forcefully take the
188: * connection back
189: */
190: void forcedClose() {
191:
192: try {
193: //if (isForcedClosed)
194: //return;
195: synchronized (this ) {
196: forcedCloseTime = System.currentTimeMillis();
197: debug.print("Forcefully closing connection for owner"
198: + owner);
199: close();
200: isForcedClosed = true;
201: }
202: } catch (SQLException sqe) {
203: debug.writeException(sqe);
204: }
205:
206: }
207:
208: public void close() throws SQLException {
209:
210: preProcess();
211: // returning connection to the pool
212: if (autoClose)
213: closeAll();
214: // roll back and set autoCommit to true if in a transaction
215: if (!conn.getAutoCommit()
216: && ((ConnectionPool) poolReference).getConfigMonitor()
217: .getConnectionLoaderClass() != null) {
218: conn.rollback();
219: conn.setAutoCommit(true);
220: }
221: debug.print("Connection Released for:" + getOwner());
222: poolReference.returnConnection(this );
223: isClosed = true;
224:
225: }
226:
227: private void closeAll() throws SQLException {
228:
229: for (int i = 0; i < references.size(); i++) {
230: Close close = (Close) references.get(i);
231: debug.print("Closing " + close);
232: if (!close.isClosed())
233: close.close();
234: }
235:
236: }
237:
238: public boolean isClosed() throws SQLException {
239:
240: return isClosed;
241:
242: }
243:
244: public DatabaseMetaData getMetaData() throws SQLException {
245:
246: preProcess();
247: return conn.getMetaData();
248:
249: }
250:
251: public void setReadOnly(boolean readOnly) throws SQLException {
252:
253: preProcess();
254: conn.setReadOnly(readOnly);
255:
256: }
257:
258: public boolean isReadOnly() throws SQLException {
259:
260: preProcess();
261: return conn.isReadOnly();
262:
263: }
264:
265: public void setCatalog(String catalog) throws SQLException {
266:
267: preProcess();
268: conn.setCatalog(catalog);
269:
270: }
271:
272: public String getCatalog() throws SQLException {
273:
274: preProcess();
275: return conn.getCatalog();
276:
277: }
278:
279: public void setTransactionIsolation(int level) throws SQLException {
280:
281: preProcess();
282: conn.setTransactionIsolation(level);
283:
284: }
285:
286: public int getTransactionIsolation() throws SQLException {
287:
288: preProcess();
289: return conn.getTransactionIsolation();
290:
291: }
292:
293: public SQLWarning getWarnings() throws SQLException {
294:
295: preProcess();
296: return conn.getWarnings();
297:
298: }
299:
300: public void clearWarnings() throws SQLException {
301:
302: preProcess();
303: conn.clearWarnings();
304:
305: }
306:
307: public Statement createStatement(int resultSetType,
308: int resultSetConcurrency) throws SQLException {
309:
310: preProcess();
311: SmartStatement stmt = new SmartStatement(conn.createStatement(
312: resultSetType, resultSetConcurrency), this );
313: if (autoClose)
314: references.add(stmt);
315: return stmt;
316:
317: }
318:
319: public PreparedStatement prepareStatement(String sql,
320: int resultSetType, int resultSetConcurrency)
321: throws SQLException {
322:
323: preProcess();
324: SmartPreparedStatement pstmt = new SmartPreparedStatement(conn
325: .prepareStatement(sql, resultSetType,
326: resultSetConcurrency), this );
327: if (autoClose)
328: references.add(pstmt);
329: return pstmt;
330:
331: }
332:
333: public CallableStatement prepareCall(String sql, int resultSetType,
334: int resultSetConcurrency) throws SQLException {
335:
336: preProcess();
337: SmartCallableStatement cstmt = new SmartCallableStatement(conn
338: .prepareCall(sql, resultSetType, resultSetConcurrency),
339: this );
340: if (autoClose)
341: references.add(cstmt);
342: return cstmt;
343:
344: }
345:
346: public java.util.Map getTypeMap() throws SQLException {
347:
348: preProcess();
349: return conn.getTypeMap();
350:
351: }
352:
353: public void setTypeMap(Map<String, Class<?>> map)
354: throws SQLException {
355: //To change body of implemented methods use File | Settings | File Templates.
356: }
357:
358: public void setHoldability(int holdability) throws SQLException {
359: //To change body of implemented methods use File | Settings | File Templates.
360: }
361:
362: public int getHoldability() throws SQLException {
363: return 0; //To change body of implemented methods use File | Settings | File Templates.
364: }
365:
366: public Savepoint setSavepoint() throws SQLException {
367: return null; //To change body of implemented methods use File | Settings | File Templates.
368: }
369:
370: public Savepoint setSavepoint(String name) throws SQLException {
371: return null; //To change body of implemented methods use File | Settings | File Templates.
372: }
373:
374: public void rollback(Savepoint savepoint) throws SQLException {
375: //To change body of implemented methods use File | Settings | File Templates.
376: }
377:
378: public void releaseSavepoint(Savepoint savepoint)
379: throws SQLException {
380: //To change body of implemented methods use File | Settings | File Templates.
381: }
382:
383: public Statement createStatement(int resultSetType,
384: int resultSetConcurrency, int resultSetHoldability)
385: throws SQLException {
386: return null; //To change body of implemented methods use File | Settings | File Templates.
387: }
388:
389: public PreparedStatement prepareStatement(String sql,
390: int resultSetType, int resultSetConcurrency,
391: int resultSetHoldability) throws SQLException {
392: return null; //To change body of implemented methods use File | Settings | File Templates.
393: }
394:
395: public CallableStatement prepareCall(String sql, int resultSetType,
396: int resultSetConcurrency, int resultSetHoldability)
397: throws SQLException {
398: return null; //To change body of implemented methods use File | Settings | File Templates.
399: }
400:
401: public PreparedStatement prepareStatement(String sql,
402: int autoGeneratedKeys) throws SQLException {
403: return null; //To change body of implemented methods use File | Settings | File Templates.
404: }
405:
406: public PreparedStatement prepareStatement(String sql,
407: int columnIndexes[]) throws SQLException {
408: return null; //To change body of implemented methods use File | Settings | File Templates.
409: }
410:
411: public PreparedStatement prepareStatement(String sql,
412: String columnNames[]) throws SQLException {
413: return null; //To change body of implemented methods use File | Settings | File Templates.
414: }
415:
416: // default access
417: Connection returnConnection() {
418:
419: return conn;
420:
421: }
422:
423: public String toString() {
424:
425: return conn.toString();
426:
427: }
428:
429: }
|