KickJava   Java API By Example, From Geeks To Geeks.

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


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: DataSourceDBConnection.java,v 1.5 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 javax.sql.DataSource JavaDoc;
36 import java.util.Enumeration JavaDoc;
37 import java.util.Hashtable JavaDoc;
38 import org.enhydra.dods.DODS;
39 import com.lutris.appserver.server.sql.standard.*;
40 import org.enhydra.dods.Common;
41 import com.lutris.logging.Logger;
42 import com.lutris.appserver.server.sql.ConnectionAllocator;
43 import com.lutris.appserver.server.sql.DBConnection;
44 import com.lutris.appserver.server.sql.ExtendedDBConnection;
45 import com.lutris.appserver.server.sql.DatabaseManagerException;
46 import com.lutris.appserver.server.sql.ExtendedConnectionAllocator;
47
48 /**
49  * Standard implementation of the DBConnection object.
50  *
51  * @see DBConnection
52  * @author Mark Diekhans
53  * @author Kyle Clark
54  * @since LBS1.7
55  * @version $Revision: 1.5 $
56  */

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

105 // private LogChannel channel = DODS.getLogChannel();
106

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

571     public synchronized void release() {
572         if (allocated) {
573         logDebug("release");
574             allocated = false;
575             if (dropConnection) {
576                 drop();
577             }
578             if (!dropped){
579                 connectionAllocator.release(this);
580             }
581         }
582     }
583     
584     /**
585      * Drop this connection from the connection allocator.
586      */

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

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

656     public int getGeneration() {
657         return generation;
658     }
659
660     /**
661      * Close this connection. Use by the connection allocator when this
662      * object is no longer used. Errors are ignored.
663      */

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

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

729     public void setAutoCommit(boolean on) throws SQLException JavaDoc {
730         validate();
731         if(Common.isChangeAutocommitEnabled(getDatabaseName())){
732                 logDebug("set autocommit: " + on);
733                 connection.setAutoCommit(on);
734           }else{
735                 logDebug("set autocommit is disabled, can't change to value :" + on);
736           }
737     }
738
739     /**
740      * Commit a transaction.
741      *
742      * @exception java.sql.SQLException If a database access error occurs.
743      */

744     public void commit() throws SQLException JavaDoc {
745         validate();
746         logDebug("commit");
747         connection.commit();
748     }
749
750     /**
751      * Rollback a transaction. Should only be used when
752      * <A HREF=#setAutoCommit>auto-commit</A> mode
753      * has been disabled.
754      *
755      * @exception java.sql.SQLException If a database access error occurs.
756      */

757     public void rollback() throws SQLException JavaDoc {
758         validate();
759         logDebug("rollback");
760         connection.rollback();
761     }
762
763     /**
764      * Debug logging.
765      *
766      * @param str
767      * The data to log.
768      */

769     protected void logDebug(String JavaDoc str) {
770         if (logging) {
771             DODS.getLogChannel().write(Logger.DEBUG,
772                     "\nDBConnection[" + id + "]:" + str + "\n");
773         }
774     }
775
776     /**
777      * Debug logging.
778      *
779      * @param str
780      * The data to log.
781      * @param stmt
782      * The statement to log.
783      */

784     protected void logDebug(String JavaDoc str, Statement JavaDoc stmt) {
785         if (logging) {
786             DODS.getLogChannel().write(Logger.DEBUG,
787                     "\nDBConnection[" + id + "]:" + str + "\n" + "SQL: "
788                     + stmt.toString());
789         }
790     }
791
792     /**
793      * Increment the count of the number of requests against
794      * this connection.
795      */

796     public void incrRequestCount() {
797         ((ExtendedConnectionAllocator) connectionAllocator).IncrementRequesteCount();
798     }
799
800     /**
801      * Get the database URL.
802      * @return The database URL.
803      */

804     public String JavaDoc getUrl() {
805         return url;
806     }
807
808     /**
809      * Get the database user name. Normally user for error messages.
810      * @return The database user name.
811      */

812     public String JavaDoc getUser() {
813         return user;
814     }
815
816     /**
817      * Get the underlying <code>Connection</code> object.
818      * Use with extreme caution.
819      * @return the connection object
820      */

821     public Connection JavaDoc getConnection() {
822         return connection;
823     }
824
825     /**
826      * @return true if this connection is marked to be dropped out
827      * of the connection pool and closed.
828      */

829     public boolean isMarkedForDrop() {
830         return dropConnection;
831     }
832
833     /**
834      * @return database name of current connection
835      *
836      */

837     public String JavaDoc getDatabaseName() {
838         return connectionAllocator.getDatabaseName();
839     }
840     /**
841      * @return connectionUsageCounter
842      */

843     public int getConnectionUsageCounter() {
844         return connectionUsageCounter;
845     }
846
847     /**
848      * @param i new value for connectionUsageCounter
849      */

850     public void setConnectionUsageCounter(int i) {
851         connectionUsageCounter = i;
852     }
853     /**
854      * @return dropped
855      */

856     public boolean isDroped() {
857         return dropped;
858     }
859     /**
860      * @return dropped
861      */

862     public boolean isClosed() {
863         return closed;
864     }
865
866     /* (non-Javadoc)
867      * @see com.lutris.appserver.server.sql.ExtendedDBConnection#setConnectionEnterPoolTime(int)
868      */

869     public void setConnectionEnterPoolTime(long i) {
870         connectionEnterPoolTime=i;
871
872     }
873
874     /* (non-Javadoc)
875      * @see com.lutris.appserver.server.sql.ExtendedDBConnection#getConnectionEnterPoolTime()
876      */

877     public long getConnectionEnterPoolTime() {
878         return connectionEnterPoolTime;
879     }
880
881     /**
882      * @return Returns the maxPreparedStmts.
883      */

884     public int getMaxPreparedStmts() {
885         return maxPreparedStmts;
886     }
887
888
889     public long curtime=0;
890
891
892 }
893
Popular Tags