001: /*
002: * NEMESIS-FORUM.
003: * Copyright (C) 2002 David Laurent(lithium2@free.fr). All rights reserved.
004: *
005: * Copyright (c) 2000 The Apache Software Foundation. All rights reserved.
006: *
007: * Copyright (C) 2001 Yasna.com. All rights reserved.
008: *
009: * Copyright (C) 2000 CoolServlets.com. All rights reserved.
010: *
011: * NEMESIS-FORUM. is free software; you can redistribute it and/or
012: * modify it under the terms of the Apache Software License, Version 1.1,
013: * or (at your option) any later version.
014: *
015: * NEMESIS-FORUM core framework, NEMESIS-FORUM backoffice, NEMESIS-FORUM frontoffice
016: * application are parts of NEMESIS-FORUM and are distributed under
017: * same terms of licence.
018: *
019: *
020: * NEMESIS-FORUM includes software developed by the Apache Software Foundation (http://www.apache.org/)
021: * and software developed by CoolServlets.com (http://www.coolservlets.com).
022: * and software developed by Yasna.com (http://www.yasna.com).
023: *
024: */
025: package org.nemesis.forum.util.jdbc;
026:
027: import java.io.IOException;
028: import java.sql.*;
029: import java.util.Date;
030: import java.util.Map;
031:
032: import org.apache.commons.logging.Log;
033: import org.apache.commons.logging.LogFactory;
034: import org.nemesis.forum.config.ConfigLoader;
035:
036: /**
037: * Default connection provider. It uses the excellent connection pool
038: * available from http://www.javaexchange.com. This connection provider is a
039: * a good choice unless you can use a container-managed one.
040: *
041: *
042: * <p>there is a compile-time dependencies on the
043: * <code>java.sql.Connection</code> class, which changed between JDK 1.3 and
044: * JDK 1.4.</p>
045: */
046: public class DbConnectionDefaultPool extends DbConnectionProvider {
047:
048: static protected Log log = LogFactory
049: .getLog(DbConnectionDefaultPool.class);
050:
051: private static final boolean POOLED = true;
052:
053: private ConnectionPool connectionPool = null;
054: //private Properties props;
055: //private Properties propDescriptions;
056:
057: private Object initLock = new Object();
058:
059: public DbConnectionDefaultPool() {
060:
061: }
062:
063: /**
064: * Returns a database connection.
065: */
066: public Connection getConnection() {
067: if (connectionPool == null) {
068: //block until the init has been done
069: synchronized (initLock) {
070: //if still null, something has gone wrong
071: if (connectionPool == null) {
072: log
073: .error("Warning: DbConnectionDefaultPool.getConnection() was "
074: + "called when the internal pool has not been initialized.");
075: return null;
076: }
077: }
078: }
079: return new ConnectionWrapper(connectionPool.getConnection(),
080: connectionPool);
081: }
082:
083: /**
084: * Starts the pool.
085: */
086: protected void start() {
087: //acquire lock so that no connections can be returned.
088: synchronized (initLock) {
089: //Get properties
090: String driver = ConfigLoader.getInstance().getConfig()
091: .getJDBCProviderProperties().getProperty("driver");
092: String server = ConfigLoader.getInstance().getConfig()
093: .getJDBCProviderProperties().getProperty("url");
094: String username = ConfigLoader.getInstance().getConfig()
095: .getJDBCProviderProperties()
096: .getProperty("username");
097: String password = ConfigLoader.getInstance().getConfig()
098: .getJDBCProviderProperties()
099: .getProperty("password");
100: int minConnections = 1, maxConnections = 5;
101: double connectionTimeout = 0.1;
102:
103: try {
104:
105: minConnections = Integer.parseInt(ConfigLoader
106: .getInstance().getConfig()
107: .getJDBCProviderProperties().getProperty(
108: "minConnections"));
109: maxConnections = Integer.parseInt(ConfigLoader
110: .getInstance().getConfig()
111: .getJDBCProviderProperties().getProperty(
112: "maxConnections"));
113: connectionTimeout = Double.parseDouble(ConfigLoader
114: .getInstance().getConfig()
115: .getJDBCProviderProperties().getProperty(
116: "connectionTimeout"));
117:
118: } catch (Exception e) {
119: log.error("your config is malformed", e);
120: }
121:
122: try {
123: connectionPool = new ConnectionPool(driver, server,
124: username, password, minConnections,
125: maxConnections, connectionTimeout);
126: } catch (IOException ioe) {
127: log.error("Error starting DbConnectionDefaultPool: ",
128: ioe);
129: }
130: }
131: }
132:
133: /**
134: * Restarts the pool to take into account any property changes.
135: */
136: protected void restart() {
137: //Kill off pool.
138: destroy();
139: //Start a new pool.
140: start();
141: }
142:
143: /**
144: * Destroys the connection pool.
145: */
146: protected void destroy() {
147: if (connectionPool != null) {
148: try {
149: connectionPool.destroy(1);
150: } catch (Exception e) {
151: log.error("", e);
152: }
153: }
154: //Release reference to connectionPool
155: connectionPool = null;
156: }
157:
158: /**
159: * DbConnectionBroker
160: * @version 1.0.11 12/7/99
161: * @author Marc A. Mnich
162: *
163: * ----------------------------------------
164: * Modified June 18, 2000 by Matt Tucker
165: * Changes:
166: * - New package name, class name to make it nice to embed as
167: * an internal class.
168: * - Source code reformatting.
169: * - Added more error handling code in constructor, createConn method
170: * so that more information is given to Yazd users.
171: * DbConnectionBroker rules! Download it from javaexchange.com
172: * ----------------------------------------
173: *
174: * DbConnectionBroker
175: * A servlet-based broker for database connections.
176: * Creates and manages a pool of database connections.
177: * @version 1.0.11 12/7/99
178: * @author Marc A. Mnich
179: */
180: private class ConnectionPool implements Runnable {
181: private Thread runner;
182:
183: private Connection[] connPool;
184: private int[] connStatus;
185:
186: private long[] connLockTime, connCreateDate;
187: private String[] connID;
188: private String dbDriver, dbServer, dbLogin, dbPassword;
189: private int currConnections, connLast, minConns, maxConns,
190: maxConnMSec;
191:
192: //available: set to false on destroy, checked by getConnection()
193: private boolean available = true;
194:
195: private SQLWarning currSQLWarning;
196: private String pid;
197:
198: /**
199: * Creates a new Connection Broker<br>
200: * dbDriver: JDBC driver. e.g. 'oracle.jdbc.driver.OracleDriver'<br>
201: * dbServer: JDBC connect string. e.g. 'jdbc:oracle:thin:@203.92.21.109:1526:orcl'<br>
202: * dbLogin: Database login name. e.g. 'Scott'<br>
203: * dbPassword: Database password. e.g. 'Tiger'<br>
204: * minConns: Minimum number of connections to start with.<br>
205: * maxConns: Maximum number of connections in dynamic pool.<br>
206: * logFileString: Absolute path name for log file. e.g. 'c:\temp\mylog.log' <br>
207: * maxConnTime: Time in days between connection resets. (Reset does a basic cleanup)<br>
208: */
209: public ConnectionPool(String dbDriver, String dbServer,
210: String dbLogin, String dbPassword, int minConns,
211: int maxConns, double maxConnTime) throws IOException {
212: connPool = new Connection[maxConns];
213: connStatus = new int[maxConns];
214: connLockTime = new long[maxConns];
215: connCreateDate = new long[maxConns];
216: connID = new String[maxConns];
217: currConnections = minConns;
218: this .maxConns = maxConns;
219: this .dbDriver = dbDriver;
220: this .dbServer = dbServer;
221: this .dbLogin = dbLogin;
222: this .dbPassword = dbPassword;
223:
224: maxConnMSec = (int) (maxConnTime * 86400000.0); //86400 sec/day
225: if (maxConnMSec < 30000) { // Recycle no less than 30 seconds.
226: maxConnMSec = 30000;
227: }
228:
229: // Write the pid file (used to clean up dead/broken connection)
230:
231: log.info("Starting ConnectionPool:");
232: log.info("dbDriver = " + dbDriver);
233: log.info("dbServer = " + dbServer);
234: log.info("dbLogin = " + dbLogin);
235: log.info("minconnections = " + minConns);
236: log.info("maxconnections = " + maxConns);
237: log.info("Total refresh interval = " + maxConnTime
238: + " days");
239: log.info("-----------------------------------------");
240:
241: // Initialize the pool of connections with the mininum connections:
242: // Problems creating connections may be caused during reboot when the
243: // servlet is started before the database is ready. Handle this
244: // by waiting and trying again. The loop allows 5 minutes for
245: // db reboot.
246: boolean connectionsSucceeded = false;
247: int dbLoop = 20;
248:
249: try {
250: for (int i = 1; i < dbLoop; i++) {
251: try {
252: for (int j = 0; j < currConnections; j++) {
253: createConn(j);
254: }
255: connectionsSucceeded = true;
256: break;
257: } catch (SQLException e) {
258: log
259: .warn(
260: "--->Attempt ("
261: + String.valueOf(i)
262: + " of "
263: + String
264: .valueOf(dbLoop)
265: + ") failed to create new connections set at startup: ",
266: e);
267: log.info(" Will try again in 15 seconds...");
268: try {
269: Thread.sleep(15000);
270: } catch (InterruptedException e1) {
271: }
272: }
273: }
274: if (!connectionsSucceeded) { // All attempts at connecting to db exhausted
275: log
276: .warn("\r\nAll attempts at connecting to Database exhausted");
277: throw new IOException();
278: }
279: } catch (Exception e) {
280: log.error("", e);
281: throw new IOException();
282: }
283:
284: // Fire up the background housekeeping thread
285:
286: runner = new Thread(this );
287: runner.start();
288:
289: } //End ConnectionPool()
290:
291: /**
292: * Housekeeping thread. Runs in the background with low CPU overhead.
293: * Connections are checked for warnings and closure and are periodically
294: * restarted.
295: * This thread is a catchall for corrupted
296: * connections and prevents the buildup of open cursors. (Open cursors
297: * result when the application fails to close a Statement).
298: * This method acts as fault tolerance for bad connection/statement programming.
299: */
300: public void run() {
301: boolean forever = true;
302: Statement stmt = null;
303: String currCatalog = null;
304:
305: while (forever) {
306:
307: // Get any Warnings on connections and print to event file
308: for (int i = 0; i < currConnections; i++) {
309: try {
310: currSQLWarning = connPool[i].getWarnings();
311: if (currSQLWarning != null) {
312: log.warn("Warnings on connection "
313: + String.valueOf(i) + " "
314: + currSQLWarning);
315: connPool[i].clearWarnings();
316: }
317: } catch (SQLException e) {
318: log.info("Cannot access Warnings: " + e);
319: }
320: }
321:
322: for (int i = 0; i < currConnections; i++) { // Do for each connection
323: long age = System.currentTimeMillis()
324: - connCreateDate[i];
325:
326: synchronized (connStatus) {
327: if (connStatus[i] > 0) { // In use, catch it next time!
328: continue;
329: }
330: connStatus[i] = 2; // Take offline (2 indicates housekeeping lock)
331: }
332:
333: try { // Test the connection with createStatement call
334: if (age > maxConnMSec) { // Force a reset at the max conn time
335: throw new SQLException();
336: }
337:
338: stmt = connPool[i].createStatement();
339: connStatus[i] = 0; // Connection is O.K.
340: //log.println("Connection confirmed for conn = " +
341: // String.valueOf(i));
342:
343: // Some DBs return an object even if DB is shut down
344: if (connPool[i].isClosed()) {
345: throw new SQLException();
346: }
347: // Connection has a problem, restart it
348: } catch (SQLException e) {
349: try {
350: log.info(new Date().toString()
351: + " ***** Recycling connection "
352: + String.valueOf(i) + ":");
353:
354: connPool[i].close();
355: createConn(i);
356: } catch (SQLException e1) {
357: log.error("Failed: ", e1);
358: connStatus[i] = 0; // Can't open, try again next time
359: }
360: } finally {
361: try {
362: if (stmt != null) {
363: stmt.close();
364: }
365: } catch (SQLException e1) {
366: }
367: ;
368: }
369: }
370:
371: try {
372: Thread.sleep(20000);
373: } // Wait 20 seconds for next cycle
374: catch (InterruptedException e) {
375: // Returning from the run method sets the internal
376: // flag referenced by Thread.isAlive() to false.
377: // This is required because we don't use stop() to
378: // shutdown this thread.
379: return;
380: }
381: }
382: } // End run
383:
384: /**
385: * This method hands out the connections in round-robin order.
386: * This prevents a faulty connection from locking
387: * up an application entirely. A browser 'refresh' will
388: * get the next connection while the faulty
389: * connection is cleaned up by the housekeeping thread.
390: *
391: * If the min number of threads are ever exhausted, new
392: * threads are added up the the max thread count.
393: * Finally, if all threads are in use, this method waits
394: * 2 seconds and tries again, up to ten times. After that, it
395: * returns a null.
396: */
397: public Connection getConnection() {
398:
399: Connection conn = null;
400:
401: if (available) {
402: boolean gotOne = false;
403:
404: for (int outerloop = 1; outerloop <= 10; outerloop++) {
405:
406: try {
407: int loop = 0;
408: int roundRobin = connLast + 1;
409: if (roundRobin >= currConnections)
410: roundRobin = 0;
411:
412: do {
413: synchronized (connStatus) {
414: if ((connStatus[roundRobin] < 1)
415: && (!connPool[roundRobin]
416: .isClosed())) {
417: conn = connPool[roundRobin];
418: connStatus[roundRobin] = 1;
419: connLockTime[roundRobin] = System
420: .currentTimeMillis();
421: connLast = roundRobin;
422: gotOne = true;
423: break;
424: } else {
425: loop++;
426: roundRobin++;
427: if (roundRobin >= currConnections)
428: roundRobin = 0;
429: }
430: }
431: } while ((gotOne == false)
432: && (loop < currConnections));
433: } catch (SQLException e1) {
434: }
435:
436: if (gotOne) {
437: break;
438: } else {
439: synchronized (this ) { // Add new connections to the pool
440: if (currConnections < maxConns) {
441: try {
442: createConn(currConnections);
443: currConnections++;
444: } catch (SQLException e) {
445: log
446: .error(
447: "Unable to create new connection: ",
448: e);
449: }
450: }
451: }
452:
453: try {
454: Thread.sleep(2000);
455: } catch (InterruptedException e) {
456: }
457: log
458: .info("-----> Connections Exhausted! Will wait and try "
459: + "again in loop "
460: + String.valueOf(outerloop));
461: }
462: } // End of try 10 times loop
463:
464: } else {
465: log
466: .error("Unsuccessful getConnection() request during destroy()");
467: } // End if(available)
468:
469: return conn;
470: }
471:
472: /**
473: * Returns the local JDBC ID for a connection.
474: */
475: public int idOfConnection(Connection conn) {
476: int match;
477: String tag;
478:
479: try {
480: tag = conn.toString();
481: } catch (NullPointerException e1) {
482: tag = "none";
483: }
484:
485: match = -1;
486:
487: for (int i = 0; i < currConnections; i++) {
488: if (connID[i].equals(tag)) {
489: match = i;
490: break;
491: }
492: }
493: return match;
494: }
495:
496: /**
497: * Frees a connection. Replaces connection back into the main pool for
498: * reuse.
499: */
500: public String freeConnection(Connection conn) {
501: String res = "";
502:
503: int this conn = idOfConnection(conn);
504: if (this conn >= 0) {
505: connStatus[this conn] = 0;
506: res = "freed " + conn.toString();
507: //log.println("Freed connection " + String.valueOf(thisconn) +
508: // " normal exit: ");
509: } else {
510: log.warn("----> Could not free connection!!!");
511: }
512:
513: return res;
514: }
515:
516: /**
517: * Returns the age of a connection -- the time since it was handed out to
518: * an application.
519: */
520: public long getAge(Connection conn) { // Returns the age of the connection in millisec.
521: int this conn = idOfConnection(conn);
522: return System.currentTimeMillis() - connLockTime[this conn];
523: }
524:
525: private void createConn(int i) throws SQLException {
526: Date now = new Date();
527: try {
528: Class.forName(dbDriver);
529: connPool[i] = DriverManager.getConnection(dbServer,
530: dbLogin, dbPassword);
531: connStatus[i] = 0;
532: connID[i] = connPool[i].toString();
533: connLockTime[i] = 0;
534: connCreateDate[i] = now.getTime();
535:
536: log.info(now.toString() + " Opening connection "
537: + String.valueOf(i) + " "
538: + connPool[i].toString() + ":");
539: } catch (ClassNotFoundException e2) {
540: log.error("", e2);
541: throw new SQLException(e2.getMessage());
542: }
543: }
544:
545: /**
546: * Shuts down the housekeeping thread and closes all connections
547: * in the pool. Call this method from the destroy() method of the servlet.
548: */
549:
550: /**
551: * Multi-phase shutdown. having following sequence:
552: * <OL>
553: * <LI><code>getConnection()</code> will refuse to return connections.
554: * <LI>The housekeeping thread is shut down.<br>
555: * Up to the time of <code>millis</code> milliseconds after shutdown of
556: * the housekeeping thread, <code>freeConnection()</code> can still be
557: * called to return used connections.
558: * <LI>After <code>millis</code> milliseconds after the shutdown of the
559: * housekeeping thread, all connections in the pool are closed.
560: * <LI>If any connections were in use while being closed then a
561: * <code>SQLException</code> is thrown.
562: * <LI>The log is closed.
563: * </OL><br>
564: * Call this method from a servlet destroy() method.
565: *
566: * @param millis the time to wait in milliseconds.
567: * @exception SQLException if connections were in use after
568: * <code>millis</code>.
569: */
570: public void destroy(int millis) throws SQLException {
571:
572: // Checking for invalid negative arguments is not necessary,
573: // Thread.join() does this already in runner.join().
574:
575: // Stop issuing connections
576: available = false;
577:
578: // Shut down the background housekeeping thread
579: runner.interrupt();
580:
581: // Wait until the housekeeping thread has died.
582: try {
583: runner.join(millis);
584: } catch (InterruptedException e) {
585: } // ignore
586:
587: // The housekeeping thread could still be running
588: // (e.g. if millis is too small). This case is ignored.
589: // At worst, this method will throw an exception with the
590: // clear indication that the timeout was too short.
591:
592: long startTime = System.currentTimeMillis();
593:
594: // Wait for freeConnection() to return any connections
595: // that are still used at this time.
596: int useCount;
597: while ((useCount = getUseCount()) > 0
598: && System.currentTimeMillis() - startTime <= millis) {
599: try {
600: Thread.sleep(500);
601: } catch (InterruptedException e) {
602: } // ignore
603: }
604:
605: // Close all connections, whether safe or not
606: for (int i = 0; i < currConnections; i++) {
607: try {
608: connPool[i].close();
609: } catch (SQLException e1) {
610: log.warn("Cannot close connections on Destroy");
611: }
612: }
613:
614: if (useCount > 0) {
615: //bt-test successful
616: String msg = "Unsafe shutdown: Had to close "
617: + useCount + " active DB connections after "
618: + millis + "ms";
619: log.warn(msg);
620:
621: // Throwing following Exception is essential because servlet authors
622: // are likely to have their own error logging requirements.
623: throw new SQLException(msg);
624: }
625:
626: } //End destroy()
627:
628: /**
629: * Less safe shutdown. Uses default timeout value.
630: * This method simply calls the <code>destroy()</code> method
631: * with a <code>millis</code>
632: * value of 10000 (10 seconds) and ignores <code>SQLException</code>
633: * thrown by that method.
634: * @see #destroy(int)
635: */
636: public void destroy() {
637: try {
638: destroy(10000);
639: } catch (SQLException e) {
640: }
641: }
642:
643: /**
644: * Returns the number of connections in use.
645: */
646: // This method could be reduced to return a counter that is
647: // maintained by all methods that update connStatus.
648: // However, it is more efficient to do it this way because:
649: // Updating the counter would put an additional burden on the most
650: // frequently used methods; in comparison, this method is
651: // rarely used (although essential).
652: public int getUseCount() {
653: int useCount = 0;
654: synchronized (connStatus) {
655: for (int i = 0; i < currConnections; i++) {
656: if (connStatus[i] > 0) { // In use
657: useCount++;
658: }
659: }
660: }
661: return useCount;
662: } //End getUseCount()
663:
664: /**
665: * Returns the number of connections in the dynamic pool.
666: */
667: public int getSize() {
668: return currConnections;
669: } //End getSize()
670:
671: } // End class
672:
673: /**
674: * An implementation of the Connection interface that wraps an underlying
675: * Connection object. It releases the connection back to a connection pool
676: * when Connection.close() is called.
677: */
678: public class ConnectionWrapper implements Connection {
679:
680: private Connection connection;
681: private ConnectionPool connectionPool;
682:
683: public ConnectionWrapper(Connection connection,
684: ConnectionPool connectionPool) {
685: this .connection = connection;
686: this .connectionPool = connectionPool;
687: }
688:
689: /**
690: * Instead of closing the underlying connection, we simply release
691: * it back into the pool.
692: */
693: public void close() throws SQLException {
694: connectionPool.freeConnection(this .connection);
695: //Release object references. Any further method calls on the
696: //connection will fail.
697: connection = null;
698: connectionPool = null;
699: }
700:
701: public String toString() {
702: if (connection != null) {
703: return connection.toString();
704: } else {
705: return "connection wrapper";
706: }
707: }
708:
709: public Statement createStatement() throws SQLException {
710: return connection.createStatement();
711: }
712:
713: public PreparedStatement prepareStatement(String sql)
714: throws SQLException {
715: return connection.prepareStatement(sql);
716: }
717:
718: public CallableStatement prepareCall(String sql)
719: throws SQLException {
720: return connection.prepareCall(sql);
721: }
722:
723: public String nativeSQL(String sql) throws SQLException {
724: return connection.nativeSQL(sql);
725: }
726:
727: public void setAutoCommit(boolean autoCommit)
728: throws SQLException {
729: connection.setAutoCommit(autoCommit);
730: }
731:
732: public boolean getAutoCommit() throws SQLException {
733: return connection.getAutoCommit();
734: }
735:
736: public void commit() throws SQLException {
737: connection.commit();
738: }
739:
740: public void rollback() throws SQLException {
741: connection.rollback();
742: }
743:
744: public boolean isClosed() throws SQLException {
745: return connection.isClosed();
746: }
747:
748: public DatabaseMetaData getMetaData() throws SQLException {
749: return connection.getMetaData();
750: }
751:
752: public void setReadOnly(boolean readOnly) throws SQLException {
753: connection.setReadOnly(readOnly);
754: }
755:
756: public boolean isReadOnly() throws SQLException {
757: return connection.isReadOnly();
758: }
759:
760: public void setCatalog(String catalog) throws SQLException {
761: connection.setCatalog(catalog);
762: }
763:
764: public String getCatalog() throws SQLException {
765: return connection.getCatalog();
766: }
767:
768: public void setTransactionIsolation(int level)
769: throws SQLException {
770: connection.setTransactionIsolation(level);
771: }
772:
773: public int getTransactionIsolation() throws SQLException {
774: return connection.getTransactionIsolation();
775: }
776:
777: public SQLWarning getWarnings() throws SQLException {
778: return connection.getWarnings();
779: }
780:
781: public void clearWarnings() throws SQLException {
782: connection.clearWarnings();
783: }
784:
785: public Statement createStatement(int resultSetType,
786: int resultSetConcurrency) throws SQLException {
787: return connection.createStatement(resultSetType,
788: resultSetConcurrency);
789: }
790:
791: public PreparedStatement prepareStatement(String sql,
792: int resultSetType, int resultSetConcurrency)
793: throws SQLException {
794: return connection.prepareStatement(sql, resultSetType,
795: resultSetConcurrency);
796: }
797:
798: public CallableStatement prepareCall(String sql,
799: int resultSetType, int resultSetConcurrency)
800: throws SQLException {
801: return connection.prepareCall(sql, resultSetType,
802: resultSetConcurrency);
803: }
804:
805: public Map getTypeMap() throws SQLException {
806: return connection.getTypeMap();
807: }
808:
809: public void setTypeMap(Map map) throws SQLException {
810: connection.setTypeMap(map);
811: }
812:
813: //------------------------------------------------------ajout dlaurent
814:
815: //comment below to compile with a jdk 1.3
816: /**
817: * @see java.sql.Connection#createStatement(int, int, int)
818: */
819: public Statement createStatement(int resultSetType,
820: int resultSetConcurrency, int resultSetHoldability)
821: throws SQLException {
822: return connection.createStatement(resultSetType,
823: resultSetConcurrency, resultSetHoldability);
824: }
825:
826: /**
827: * @see java.sql.Connection#getHoldability()
828: */
829: public int getHoldability() throws SQLException {
830: return connection.getHoldability();
831: }
832:
833: /**
834: * @see java.sql.Connection#prepareCall(String, int, int, int)
835: */
836: public CallableStatement prepareCall(String sql,
837: int resultSetType, int resultSetConcurrency,
838: int resultSetHoldability) throws SQLException {
839: return connection.prepareCall(sql, resultSetType,
840: resultSetConcurrency, resultSetHoldability);
841: }
842:
843: /**
844: * @see java.sql.Connection#prepareStatement(String, int, int, int)
845: */
846: public PreparedStatement prepareStatement(String sql,
847: int resultSetType, int resultSetConcurrency,
848: int resultSetHoldability) throws SQLException {
849: return connection.prepareStatement(sql, resultSetType,
850: resultSetConcurrency, resultSetHoldability);
851: }
852:
853: /**
854: * @see java.sql.Connection#prepareStatement(String, int)
855: */
856: public PreparedStatement prepareStatement(String sql,
857: int autoGeneratedKeys) throws SQLException {
858: return connection.prepareStatement(sql, autoGeneratedKeys);
859: }
860:
861: /**
862: * @see java.sql.Connection#prepareStatement(String, int[])
863: */
864: public PreparedStatement prepareStatement(String sql,
865: int[] columnIndexes) throws SQLException {
866: return connection.prepareStatement(sql, columnIndexes);
867: }
868:
869: /**
870: * @see java.sql.Connection#prepareStatement(String, String[])
871: */
872: public PreparedStatement prepareStatement(String sql,
873: String[] columnNames) throws SQLException {
874: return connection.prepareStatement(sql, columnNames);
875: }
876:
877: /**
878: * @see java.sql.Connection#releaseSavepoint(Savepoint)
879: */
880: public void releaseSavepoint(Savepoint savepoint)
881: throws SQLException {
882: connection.releaseSavepoint(savepoint);
883: }
884:
885: /**
886: * @see java.sql.Connection#rollback(Savepoint)
887: */
888: public void rollback(Savepoint savepoint) throws SQLException {
889: connection.rollback(savepoint);
890: }
891:
892: /**
893: * @see java.sql.Connection#setHoldability(int)
894: */
895: public void setHoldability(int holdability) throws SQLException {
896: connection.setHoldability(holdability);
897: }
898:
899: /**
900: * @see java.sql.Connection#setSavepoint()
901: */
902: public Savepoint setSavepoint() throws SQLException {
903: return connection.setSavepoint();
904: }
905:
906: /**
907: * @see java.sql.Connection#setSavepoint(String)
908: */
909: public Savepoint setSavepoint(String name) throws SQLException {
910: return connection.setSavepoint(name);
911: }
912:
913: }
914: }
|