KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > lutris > appserver > server > sql > datasource > SimpleDataSourceDBConnection


1 /*
2  * Enhydra Java Application Server Project
3  *
4  * The contents of this file are subject to the Enhydra Public License
5  * Version 1.1 (the "License"); you may not use this file except in
6  * compliance with the License. You may obtain a copy of the License on
7  * the Enhydra web site ( http://www.enhydra.org/ ).
8  *
9  * Software distributed under the License is distributed on an "AS IS"
10  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
11  * the License for the specific terms governing rights and limitations
12  * under the License.
13  *
14  * The Initial Developer of the Enhydra Application Server is Lutris
15  * Technologies, Inc. The Enhydra Application Server and portions created
16  * by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
17  * All Rights Reserved.
18  *
19  * Contributor(s):
20  *
21  * $Id: SimpleDataSourceDBConnection.java,v 1.1 2005/05/26 08:08:10 predrag Exp $
22  *
23  * formatted with JxBeauty (c) johann.langhofer@nextra.at
24  */

25 package com.lutris.appserver.server.sql.datasource;
26
27 import java.sql.CallableStatement JavaDoc;
28 import java.sql.Connection JavaDoc;
29 import java.sql.DriverManager JavaDoc;
30 import java.sql.PreparedStatement JavaDoc;
31 import java.sql.ResultSet JavaDoc;
32 import java.sql.SQLException JavaDoc;
33 import java.sql.SQLWarning JavaDoc;
34 import java.sql.Statement JavaDoc;
35 import java.util.Enumeration JavaDoc;
36 import java.util.Hashtable JavaDoc;
37
38 import javax.sql.DataSource JavaDoc;
39
40 import org.enhydra.dods.Common;
41 import org.enhydra.dods.DODS;
42
43 import com.lutris.appserver.server.sql.ConnectionAllocator;
44 import com.lutris.appserver.server.sql.DBConnection;
45 import com.lutris.appserver.server.sql.DatabaseManagerException;
46 import com.lutris.appserver.server.sql.ExtendedConnectionAllocator;
47 import com.lutris.appserver.server.sql.ExtendedDBConnection;
48 import com.lutris.appserver.server.sql.standard.StandardLogicalDatabase;
49 import com.lutris.logging.Logger;
50
51 /**
52  * Standard implementation of the DBConnection object.
53  *
54  * @see DBConnection
55  * @author Mark Diekhans
56  * @author Kyle Clark
57  * @since LBS1.7
58  * @version $Revision: 1.1 $
59  */

60 public class SimpleDataSourceDBConnection implements ExtendedDBConnection {
61
62     /** JDBC connection object. */
63     protected Connection JavaDoc connection;
64
65     /** Database URL, used for error messages. */
66     protected String JavaDoc url;
67
68     /** Database user, for error messages. */
69     protected String JavaDoc user;
70     
71     protected DataSource JavaDoc ds;
72
73     /** Database user password. */
74     protected String JavaDoc password;
75     // Identifier for this connection.
76
protected int id;
77     // Next available identifier for a connection.
78
protected static int nextId = 0;
79     // Table of prepared (compiled) statements, keyed by SQL.
80
protected Hashtable JavaDoc preparedStmtCache;
81     // The last statement used by this connection.
82
protected Statement JavaDoc currentStmt = null;
83     // The connection allocator this connection is associated with.
84
protected ConnectionAllocator connectionAllocator;
85     // Indicates if logging is enabled.
86
protected boolean logging;
87     // Generation number assigned and used by StandardConnectionAllocator.
88
protected int generation;
89     // Has this connection been closed.
90
protected boolean closed = false;
91     // Do we need to drop this connection?
92
protected boolean dropConnection = false;
93     // Has this connection been dropped?
94
protected boolean dropped = false;
95     // Has this connectio been closed.
96
protected boolean reset = true;
97     // Is this connection currently in use.
98
protected boolean allocated = false;
99     // Maximum number of open statements.
100
protected int maxPreparedStmts;
101     // the number of times a particular DBConnection was allocated;
102
protected int connectionUsageCounter=0;
103     // Time when connection is released to pool;
104
protected long connectionEnterPoolTime = -1;
105     /**
106      * The log channel.
107      */

108 // private LogChannel channel = DODS.getLogChannel();
109

110     /**
111      * Initialize the connection to a database.
112      *
113      * @param url JDBC URL of database.
114      * @param user SQL user name.
115      * @param password SQL password.
116      * @param connectionAllocatorObj The connection allocator that this
117      * connection belongs to.
118      * @param maxPreparedStatements Maximum number of preparse statements.
119      * a value of less than zero queries JDBC for the value.
120      * @param logging Specifying <CODE>true</CODE> enables SQL logging.
121      * @param generation A generation number used to drop old connection
122      * when they are released.
123      * @exception java.sql.SQLException If a connection can't be established.
124      */

125     public SimpleDataSourceDBConnection(ConnectionAllocator connectionAllocatorObj,
126             String JavaDoc url, String JavaDoc user, String JavaDoc password, int maxPreparedStatements,
127             boolean logging, int generation)
128         throws SQLException JavaDoc {
129         id = nextId++;
130         this.preparedStmtCache = new Hashtable JavaDoc();
131         this.connectionAllocator = connectionAllocatorObj;
132         this.url = url;
133         this.user = user;
134         this.password = password;
135         this.logging = logging;
136         this.generation = generation;
137         connection = DriverManager.getConnection(url, user, password);
138
139         currentStmt = connection.createStatement();
140         if (maxPreparedStatements < 0) {
141             // One UN-prepared statement is used up.
142
this.maxPreparedStmts = connection.getMetaData().getMaxStatements()
143                     - 1;
144             if (this.maxPreparedStmts == 0) {
145                 // Some (Microsoft) JDBC drivers return apparently incorrect
146
// value of 1, so we set this to 1, instead of throwing an
147
// error since it still works.
148
this.maxPreparedStmts = 1;
149             }
150             if (this.maxPreparedStmts < 0) {
151                 // Take a wild guess here and assume that if
152
// getMaxStatements returns '0', then it really
153
// means 'unlimited'. Assign an arbitrary number.
154
this.maxPreparedStmts = 256;
155             }
156         } else {
157             this.maxPreparedStmts = maxPreparedStatements;
158         }
159         logDebug("DBConnection[" + id + "]: " + url
160                 + "\nNew connection allocated.\n");
161         connectionEnterPoolTime = System.currentTimeMillis();
162     }
163 //sinisa 21.04.2004 Add DataSource
164
/**
165      * Initialize the connection to a database.
166      *
167      * @param ds DataSource object.
168      * @param connectionAllocatorObj The connection allocator that this
169      * connection belongs to.
170      * @param maxPreparedStatements Maximum number of preparse statements.
171      * a value of less than zero queries JDBC for the value.
172      * @param logging Specifying <CODE>true</CODE> enables SQL logging.
173      * @param generation A generation number used to drop old connection
174      * when they are released.
175      * @exception java.sql.SQLException If a connection can't be established.
176      */

177     protected SimpleDataSourceDBConnection(ConnectionAllocator connectionAllocatorObj,
178             DataSource JavaDoc dataSource, int maxPreparedStatements,
179             boolean logging, int generation)
180         throws SQLException JavaDoc {
181         id = nextId++;
182         this.preparedStmtCache = new Hashtable JavaDoc();
183         this.connectionAllocator = connectionAllocatorObj;
184         this.ds = dataSource;
185         this.logging = logging;
186         this.generation = generation;
187
188         connection = ds.getConnection();
189
190         currentStmt = connection.createStatement();
191         if (maxPreparedStatements < 0) {
192             // One UN-prepared statement is used up.
193
this.maxPreparedStmts = connection.getMetaData().getMaxStatements()
194                     - 1;
195             if (this.maxPreparedStmts == 0) {
196                 // Some (Microsoft) JDBC drivers return apparently incorrect
197
// value of 1, so we set this to 1, instead of throwing an
198
// error since it still works.
199
this.maxPreparedStmts = 1;
200             }
201             if (this.maxPreparedStmts < 0) {
202                 // Take a wild guess here and assume that if
203
// getMaxStatements returns '0', then it really
204
// means 'unlimited'. Assign an arbitrary number.
205
this.maxPreparedStmts = 256;
206             }
207         } else {
208             this.maxPreparedStmts = maxPreparedStatements;
209         }
210         logDebug("DBConnection[" + id + "]: "
211                 + "\nNew connection allocated.\n");
212         connectionEnterPoolTime = System.currentTimeMillis();
213     }
214
215     /**
216      * Method called when this connection object is allocated from the
217      * connection allocator.
218      *
219      * @exception java.sql.SQLException If <CODE>reset</CODE> had no
220      * been called on the previous operation.
221      */

222     public synchronized void allocate() throws SQLException JavaDoc {
223         logDebug("allocate");
224         try {
225             closedCheck();
226             reset();
227         } catch (SQLException JavaDoc e) {
228             handleException(e);
229             //
230
// If this connection is no longer valid we need
231
// to drop it.
232
//
233
if (dropConnection) {
234                 drop();
235             } else {
236                 release();
237             }
238             throw e;
239         }
240         reset = false;
241         allocated = true;
242     }
243
244     /**
245      * Check to see that the previous database connection
246      * has had reset called. This ensures that the database
247      * resources have always been freed in a timely manner.
248      *
249      * @exception java.sql.SQLException
250      * If <CODE>reset</CODE> has not
251      * been called on the previous operation.
252      */

253     protected void resetCheck() throws SQLException JavaDoc {
254         logDebug("resetCheck()");
255         if (!reset) {
256             throw new java.sql.SQLException JavaDoc("DBConnection.reset() was not called after the previous "
257                     + "operation completed");
258         }
259     }
260
261     /**
262      * Check to see that this database connection has
263      * has been properly allocated before is is used.
264      *
265      * @exception java.sql.SQLException
266      * If it was not properly allocated.
267      */

268     protected void allocatedCheck() throws SQLException JavaDoc {
269         logDebug("allocatedCheck()");
270         if (!allocated) {
271             throw new java.sql.SQLException JavaDoc("attempt to access connection which was released.");
272         }
273     }
274
275     /**
276      * Check to see that this database connection has
277      * has not been closed.
278      *
279      * @exception java.sql.SQLException
280      * If it is closed.
281      */

282     protected void closedCheck() throws SQLException JavaDoc {
283         logDebug("closedCheck()");
284         if (closed || getConnection().isClosed()) {
285             throw new java.sql.SQLException JavaDoc("attempt to access a closed connection.");
286         }
287     }
288
289     /**
290      * Validates this connection. Check to see that it
291      * is not closed and has been properly allocated.
292      *
293      * @exception java.sql.SQLException
294      * If it is not valid.
295      */

296     public void validate() throws SQLException JavaDoc {
297         logDebug("validate()");
298         allocatedCheck();
299         closedCheck();
300     }
301
302     /**
303      * Closes down all query-specific resources.
304      *
305      * @exception java.sql.SQLException If a database error occurs.
306      */

307     public synchronized void reset() throws SQLException JavaDoc {
308         // Try to cleanup everything, but save the first error.
309
SQLException JavaDoc saveExcept = null;
310
311         if (reset) {
312             return;
313         }
314         logDebug("reset");
315         try {
316             connection.clearWarnings();
317         } catch (SQLException JavaDoc except) {
318             if (saveExcept == null) {
319                 saveExcept = except;
320             }
321         }
322         try {
323             connection.setAutoCommit(false);
324         } catch (SQLException JavaDoc except) {
325             if (saveExcept == null) {
326                 saveExcept = except;
327             }
328         }
329         reset = true;
330         //
331
// Throw any exceptions that were generated.
332
//
333
if (saveExcept != null) {
334             throw saveExcept;
335         }
336     }
337
338     /**
339      * Get a prepared statement given an SQL string. If the statement is
340      * cached, return that statement, otherwise prepare and save in the
341      * cache.
342      *
343      * @param sql The SQL statement to prepared.
344      * @return The prepared statement, which is associated only with this
345      * connection and must not be used once the connection is released.
346      * @exception java.sql.SQLException If a SQL error occured compiling the
347      * statement.
348      */

349     public synchronized PreparedStatement JavaDoc prepareStatement(String JavaDoc sql)
350         throws SQLException JavaDoc {
351             return _prepareStatement(sql, -100, -100, false);
352     }
353
354     private synchronized PreparedStatement JavaDoc _prepareStatement(String JavaDoc sql, int iResultSetType, int iResultSetConcurrency, boolean tuned)
355         throws SQLException JavaDoc {
356         PreparedStatement JavaDoc preparedStmt = null;
357         String JavaDoc mapKey = sql+"=+=+"+iResultSetType+"=+=+"+iResultSetConcurrency+"=+=+";
358         if (tuned){
359              mapKey=mapKey+"tuned";
360         }
361         logDebug("Prepare statement: " + sql);
362         validate();
363         boolean selectQuery = sql.trim().toLowerCase().startsWith("select");
364         if(maxPreparedStmts>0 && !selectQuery){
365             preparedStmt = (PreparedStatement JavaDoc) preparedStmtCache.get(mapKey);
366             if ((preparedStmt != null) && (!preparedStmt.getConnection().isClosed())) {
367                 preparedStmt.clearParameters();
368             } else {
369                 if (preparedStmtCache.size() >= maxPreparedStmts) {
370                     String JavaDoc key = (String JavaDoc) preparedStmtCache.keys().nextElement();
371                     ((PreparedStatement JavaDoc) preparedStmtCache.remove(key)).close();
372                 }
373                 preparedStmt = getNewPrepStatemet(sql, iResultSetType, iResultSetConcurrency, tuned);
374                 preparedStmtCache.put(mapKey, preparedStmt);
375             }
376         }else{
377             preparedStmt = getNewPrepStatemet(sql, iResultSetType, iResultSetConcurrency, tuned);
378         }
379         return preparedStmt;
380     }
381
382     
383     /**
384      * @param sql The SQL statement to prepared.
385      * @param iResultSetType a result set type; one of ResultSet.TYPE_FORWARD_ONLY, ResultSet.TYPE_SCROLL_INSENSITIVE, or ResultSet.TYPE_SCROLL_SENSITIVE.
386      * @param iResultSetConcurrency a concurrency type; one of ResultSet.CONCUR_READ_ONLY or ResultSet.CONCUR_UPDATABLE.
387      * @param tuned Showing is PrepareStatment user tuned or use default setings
388      * @return New PreparedStatement
389      * @throws SQLException
390      */

391     private PreparedStatement JavaDoc getNewPrepStatemet(String JavaDoc sql, int iResultSetType, int iResultSetConcurrency, boolean tuned) throws SQLException JavaDoc {
392         PreparedStatement JavaDoc preparedStmt;
393         if(!tuned){
394             if(getResultSetType()==StandardLogicalDatabase.DEFAULT_RESULT_SET_TYPE ||
395                getResultSetConcurrency()==StandardLogicalDatabase.DEFAULT_RESULT_SET_CONCURRENCY){
396                 preparedStmt = connection.prepareStatement(sql);
397             }
398             else {
399                 preparedStmt = connection.prepareStatement(sql,getResultSetType(),getResultSetConcurrency());
400             }
401         }else{
402             preparedStmt = connection.prepareStatement(sql,iResultSetType,iResultSetConcurrency);
403         }
404         return preparedStmt;
405     }
406
407     /**
408      * Get a prepared statement given an SQL string. If the statement is
409      * cached, return that statement, otherwise prepare and save in the
410      * cache.
411      *
412      * @param sql The SQL statement to prepared.
413      * @param iResultSetType a result set type; one of ResultSet.TYPE_FORWARD_ONLY, ResultSet.TYPE_SCROLL_INSENSITIVE, or ResultSet.TYPE_SCROLL_SENSITIVE.
414      * @param iResultSetConcurrency a concurrency type; one of ResultSet.CONCUR_READ_ONLY or ResultSet.CONCUR_UPDATABLE.
415      * @return The prepared statement, which is associated only with this
416      * connection and must not be used once the connection is released.
417      * @exception java.sql.SQLException If a SQL error occured compiling the
418      * statement.
419      */

420     public synchronized PreparedStatement JavaDoc prepareStatement(String JavaDoc sql, int iResultSetType, int iResultSetConcurrency)
421         throws SQLException JavaDoc {
422         return _prepareStatement(sql, iResultSetType, iResultSetConcurrency, true);
423     }
424
425     protected int getResultSetType(){
426
427         int resultSetType;
428         try {
429             resultSetType =((StandardLogicalDatabase) DODS
430                     .getDatabaseManager()
431                     .findLogicalDatabase(getDatabaseName()))
432                     .getResultSetType();
433         } catch (DatabaseManagerException e) {
434             DODS.getLogChannel().write(Logger.DEBUG,"Error unknown logical database. Using default value for 'resultSetType' parameter");
435             resultSetType = StandardLogicalDatabase.DEFAULT_RESULT_SET_TYPE;
436         }
437         return resultSetType;
438     }
439     
440     protected int getResultSetConcurrency(){
441
442         int resultSetConcurrency;
443         try {
444             resultSetConcurrency =((StandardLogicalDatabase) DODS
445                     .getDatabaseManager()
446                     .findLogicalDatabase(getDatabaseName()))
447                     .getResultSetConcurrency();
448         } catch (DatabaseManagerException e) {
449             DODS.getLogChannel().write(Logger.DEBUG,"Error unknown logical database. Using default value for 'resultSetConcurrency' parameter");
450             resultSetConcurrency = StandardLogicalDatabase.DEFAULT_RESULT_SET_CONCURRENCY;
451         }
452         return resultSetConcurrency;
453     }
454
455
456     /**
457      * Creates a CallableStatement object for calling database
458      * stored procedures. Refer to jdk api refernece.
459      *
460      * @param sql The SQL statement to be called.
461      * @return a new CallableStatement object containing the
462      * pre-compiled SQL statement.
463      * @exception java.sql.SQLException If a database access error occurs
464      * statement.
465      */

466     public synchronized CallableStatement JavaDoc prepareCall(String JavaDoc sql) throws SQLException JavaDoc {
467         return connection.prepareCall(sql);
468     }
469
470     /**
471      * Execute a prepared query statement. Once the query has completed,
472      * <CODE>reset()</CODE> should be called.
473      *
474      * @param preparedStmt The statement to execute.
475      * @param msg for logging/debug purposes
476      * @return Query result set, do not call close, use reset(),
477      * @exception java.sql.SQLException If a SQL error occured executing the
478      * statement.
479      */

480     public synchronized ResultSet JavaDoc executeQuery(PreparedStatement JavaDoc preparedStmt, String JavaDoc msg)
481         throws SQLException JavaDoc {
482         logDebug("Execute prepared statement: " + msg, preparedStmt);
483         validate();
484         return preparedStmt.executeQuery();
485     }
486
487     /**
488      * Execute a SQL query statement. This is a wrapper that adds logging.
489      * Once the query has completed, <CODE>reset()</CODE> should be called.
490      *
491      * @param sql The SQL query statement
492      * @return Query result set, do not call close, use reset(),
493      * @exception java.sql.SQLException If a SQL error occured executing the
494      * statement.
495      */

496     public synchronized ResultSet JavaDoc executeQuery(String JavaDoc sql) throws SQLException JavaDoc {
497         logDebug(sql);
498         validate();
499         return currentStmt.executeQuery(sql);
500     }
501
502     /**
503      * Execute a SQL update statement. This is a wrapper that adds logging.
504      * Once the update has completed, <CODE>reset()</CODE> should be called.
505      *
506      * @param sql
507      * The SQL query statement
508      * @return
509      * Either the row count for UPDATE, INSERT, DELETE or 0 for
510      * SQL statements that return nothing.
511      * @exception java.sql.SQLException
512      * If a SQL error occured executing the update.
513      */

514     public synchronized int executeUpdate(String JavaDoc sql) throws SQLException JavaDoc {
515         logDebug(sql);
516         validate();
517         return currentStmt.executeUpdate(sql);
518     }
519
520     /**
521      * Execute a prepared update statement. Once the update has completed,
522      * <CODE>reset()</CODE> should be called.
523      *
524      * @param preparedStmt The statement to execute.
525      * @param msg for logging/debug purposes
526      * @return Either the row count for UPDATE, INSERT, DELETE or 0 for
527      * SQL statements that return nothing.
528      * @exception java.sql.SQLException If a SQL error occured executing the
529      * statement.
530      */

531     public int executeUpdate(PreparedStatement JavaDoc preparedStmt, String JavaDoc msg) throws SQLException JavaDoc {
532         logDebug("Execute prepared statement: " + msg, preparedStmt);
533         validate();
534         return preparedStmt.executeUpdate();
535     }
536
537     /**
538      * Execute a SQL statement that does not return a resultset. This is a
539      * wrapper that adds logging. Once the query has completed,
540      * <CODE>reset()</CODE> should be called.
541      *
542      * @param sql The SQL query statement
543      * @return True if the next result is a ResultSet; false if it is
544      * an update count or there are no more results.
545      * @exception java.sql.SQLException If a SQL error occured executing the
546      * statement.
547      */

548     public synchronized boolean execute(String JavaDoc sql) throws SQLException JavaDoc {
549         logDebug("execute: " + sql);
550         validate();
551         return currentStmt.execute(sql);
552     }
553
554     /**
555      * Check for warnings in a result set.
556      *
557      * @param resultSet The result set to check for warnings.
558      * @exception java.sql.SQLException If a SQL error occured compiling the
559      * statement.
560      */

561     public void warningCheck(ResultSet JavaDoc resultSet) throws SQLException JavaDoc {
562         logDebug("warningCheck()");
563         SQLWarning JavaDoc warning = resultSet.getWarnings();
564
565         if (warning != null) {
566             throw warning;
567         }
568     }
569
570     /**
571      * Return this connection to its allocator. This object should not be
572      * used after calling this function.
573      */

574     public synchronized void release() {
575         if (allocated) {
576             logDebug("release");
577             // compliance with WEBDOCWF begin
578
// Excelsior's patch start
579
// The synchronized block is used to prevent dead lock that
580
// was found at 7/23/2002 by Excelsior
581
synchronized (connectionAllocator) {
582                 // Excelsior's patch end
583
connectionAllocator.release(this);
584                 allocated = false;
585                 if (dropConnection) {
586                     drop();
587                 }
588             }
589         }
590     }
591
592     /**
593      * Drop this connection from the connection allocator.
594      */

595     protected synchronized void drop() {
596         if (!dropped) {
597             close();
598             logDebug("drop");
599             connectionAllocator.drop(this);
600             dropped = true;
601             logDebug("DBConnection[" + id + "]: " + url
602                     + "Connection has been dropped from the connection allocator.");
603         }
604     }
605
606     /**
607      * Check if a connection is valid after an SQL exception
608      * is thrown. If it is not usable, then the connection is
609      * dropped from the connection allocator and closed. The connection
610      * is then no longer usable.
611      *
612      * @param sqlExcept
613      * The SQL exception that occured.
614      * @return true if the exception does not affect this
615      * connection object. False otherwise - in which case
616      * this connection object is no longer usable.
617      */

618     public synchronized boolean handleException(SQLException JavaDoc sqlExcept) {
619         String JavaDoc sqlState = sqlExcept.getSQLState();
620
621         logDebug("handleException: " + sqlExcept.getMessage());
622         //
623
// TODO
624
// Need to query complete set of fatal exceptions,
625
// or complete set of non-fatal exceptions.
626
// Until then we assume all are fatal.
627
// Note: that code '11111111' is an internal exception
628
// and does not require the connection pool to be
629
// reset. This is a temporary fix. (paul)
630
// Note: There may be a bug in the pool closure logic
631
// if connections in the pool repeatidly throw exceptions
632
// that close the pool while the pool was already in the
633
// process of being closed. (paul)
634
//
635
if (sqlExcept.getErrorCode() != 11111111) {
636             if (!dropConnection) {
637                 logDebug("DBConnection[" + id + "]: " + url
638                         + "\nScheduled to be dropped from connection allocator."
639                         + "\nUnable to handle exception: \""
640                         + sqlExcept.toString() + " \nErrorCode : "
641                         + sqlExcept.getErrorCode() + " \nSQLState : "
642                         + sqlExcept.getSQLState() + "\"\n");
643                 //
644
// We need to drop this connection. N.B. We only
645
// set a flag that we want the connection dropped.
646
// We don't want the connection dropped yet (which
647
// implies closed()) because we may be in the
648
// middle of a transaction which we may want to
649
// rollback.
650
//
651
dropConnection = true;
652             }
653             return false;
654         } else {
655             return true;
656         }
657     }
658
659     /**
660      * Get the generation number specified when the connection was created.
661      *
662      * @return The generation number.
663      */

664     public int getGeneration() {
665         return generation;
666     }
667
668     /**
669      * Close this connection. Use by the connection allocator when this
670      * object is no longer used. Errors are ignored.
671      */

672     public synchronized void close() {
673         if (!closed) {
674             logDebug("close");
675
676             /*
677              * If we are closing the connection, then
678              * the prepared statements should automatically
679              * be closed. Of course, the doc isn't clear.
680              * So we attempt to close the statements.
681              * If any fail, then we ignore the rest.
682              * The reason we do this is that if the original
683              * connection is broken, then the closing of
684              * each statement needs to time out. This
685              * is very time consuming.....
686              */

687             boolean closeStmts = true;
688             //
689
// Close the prepared statements.
690
//
691
/**/
692             Enumeration JavaDoc e = preparedStmtCache.keys();
693
694             while (e.hasMoreElements() && closeStmts) {
695                 String JavaDoc key = (String JavaDoc) e.nextElement();
696
697                 try {
698                     ((PreparedStatement JavaDoc) preparedStmtCache.remove(key)).close();
699                 } catch (SQLException JavaDoc except) {
700                     // Ignore errors, we maybe handling one.
701
closeStmts = false;
702                     logDebug("DBConnection[" + id + "]: " + url
703                                  + "\nUnable to close statements. Continuing....\n");
704                 }
705             }
706             /**/
707             if (closeStmts) {
708                 try {
709                     if (currentStmt != null) {
710                         currentStmt.close();
711                     }
712                 } catch (Exception JavaDoc except) {
713                     // Ignore errors, we maybe handling one.
714
closeStmts = false;
715                 }
716                 currentStmt=null;
717             }
718             try {
719                 if(!connection.isClosed()){
720                     connection.close();
721                 }
722             } catch (Exception JavaDoc except) {// Ignore errors, we maybe handling one.
723
}
724             logDebug("DBConnection[" + id + "]: " + url
725                     + "\nConnection has been closed.\n");
726         }
727         closed = true;
728         connection = null;
729     }
730
731     /**
732      * Autocommit on/off.
733      *
734      * @param on - False to disable auto commit mode. True to enable.
735      * @exception java.sql.SQLException If a database access error occurs.
736      */

737     public void setAutoCommit(boolean on) throws SQLException JavaDoc {
738         validate();
739         if(Common.isChangeAutocommitEnabled(getDatabaseName())){
740                 logDebug("set autocommit: " + on);
741                 connection.setAutoCommit(on);
742           }else{
743                 logDebug("set autocommit is disabled, can't change to value :" + on);
744           }
745     }
746
747     /**
748      * Commit a transaction.
749      *
750      * @exception java.sql.SQLException If a database access error occurs.
751      */

752     public void commit() throws SQLException JavaDoc {
753         validate();
754         logDebug("commit");
755         connection.commit();
756     }
757
758     /**
759      * Rollback a transaction. Should only be used when
760      * <A HREF=#setAutoCommit>auto-commit</A> mode
761      * has been disabled.
762      *
763      * @exception java.sql.SQLException If a database access error occurs.
764      */

765     public void rollback() throws SQLException JavaDoc {
766         validate();
767         logDebug("rollback");
768         connection.rollback();
769     }
770
771     /**
772      * Debug logging.
773      *
774      * @param str
775      * The data to log.
776      */

777     protected void logDebug(String JavaDoc str) {
778         if (logging) {
779             DODS.getLogChannel().write(Logger.DEBUG,
780                     "\nDBConnection[" + id + "]:" + str + "\n");
781         }
782     }
783
784     /**
785      * Debug logging.
786      *
787      * @param str
788      * The data to log.
789      * @param stmt
790      * The statement to log.
791      */

792     protected void logDebug(String JavaDoc str, Statement JavaDoc stmt) {
793         if (logging) {
794             DODS.getLogChannel().write(Logger.DEBUG,
795                     "\nDBConnection[" + id + "]:" + str + "\n" + "SQL: "
796                     + stmt.toString());
797         }
798     }
799
800     /**
801      * Increment the count of the number of requests against
802      * this connection.
803      */

804     public void incrRequestCount() {
805         ((ExtendedConnectionAllocator) connectionAllocator).IncrementRequesteCount();
806     }
807
808     /**
809      * Get the database URL.
810      * @return The database URL.
811      */

812     public String JavaDoc getUrl() {
813         return url;
814     }
815
816     /**
817      * Get the database user name. Normally user for error messages.
818      * @return The database user name.
819      */

820     public String JavaDoc getUser() {
821         return user;
822     }
823
824     /**
825      * Get the underlying <code>Connection</code> object.
826      * Use with extreme caution.
827      * @return the connection object
828      */

829     public Connection JavaDoc getConnection() {
830         return connection;
831     }
832
833     /**
834      * @return true if this connection is marked to be dropped out
835      * of the connection pool and closed.
836      */

837     public boolean isMarkedForDrop() {
838         return dropConnection;
839     }
840
841     /**
842      * @return database name of current connection
843      *
844      */

845     public String JavaDoc getDatabaseName() {
846         return connectionAllocator.getDatabaseName();
847     }
848     /**
849      * @return connectionUsageCounter
850      */

851     public int getConnectionUsageCounter() {
852         return connectionUsageCounter;
853     }
854
855     /**
856      * @param i new value for connectionUsageCounter
857      */

858     public void setConnectionUsageCounter(int i) {
859         connectionUsageCounter = i;
860     }
861     /**
862      * @return dropped
863      */

864     public boolean isDroped() {
865         return dropped;
866     }
867     /**
868      * @return dropped
869      */

870     public boolean isClosed() {
871         return closed;
872     }
873
874     /* (non-Javadoc)
875      * @see com.lutris.appserver.server.sql.ExtendedDBConnection#setConnectionEnterPoolTime(int)
876      */

877     public void setConnectionEnterPoolTime(long i) {
878         connectionEnterPoolTime=i;
879
880     }
881
882     /* (non-Javadoc)
883      * @see com.lutris.appserver.server.sql.ExtendedDBConnection#getConnectionEnterPoolTime()
884      */

885     public long getConnectionEnterPoolTime() {
886         return connectionEnterPoolTime;
887     }
888
889     /**
890      * @return Returns the maxPreparedStmts.
891      */

892     public int getMaxPreparedStmts() {
893         return maxPreparedStmts;
894     }
895 }
896
Popular Tags