001: package com.sun.portal.app.filesharing.util;
002:
003: import com.sun.portal.app.filesharing.repo.RepoException;
004:
005: import javax.naming.Context;
006: import javax.naming.InitialContext;
007: import javax.naming.NamingException;
008: import javax.sql.DataSource;
009: import java.sql.Connection;
010: import java.sql.DriverManager;
011: import java.sql.SQLException;
012: import java.util.Properties;
013: import java.util.logging.Level;
014: import java.util.logging.Logger;
015:
016: /**
017: * The SQLExecutor encapsulates execution of JDBC operations using the command pattern.
018: * <p>
019: * JDBC operations should be done within the run() method of a SQLTask implementation using
020: * the JDBC connection passed as parameter.
021: * <p>
022: * When the SQLExecutor execute(SQLTask) method is invoked, it invokes the SQLTask run(Connection)
023: * method with a live JDBC connection. The connection is closed and recycled by the SQLExecutor
024: * after the SQLTask run() method finishes.
025: * <p>
026: * @author Alejandro Abdelnur
027: *
028: */
029: public class SQLExecutor {
030:
031: private static Logger _logger = LogUtils.getInstance().getLogger(
032: SQLExecutor.class.getName());
033:
034: private String _datasource;
035:
036: private static String _driver;
037: private static String _jdbcUrl;
038: private static Properties _jdbcProps;
039:
040: public SQLExecutor(String datasource) {
041: _datasource = datasource;
042: }
043:
044: // FOR UNIT TEST PURPOSES ONLY
045: public static void setJdbcForTest(String driver, String jdbcUrl,
046: Properties jdbcProps) {
047: _driver = driver;
048: _jdbcUrl = jdbcUrl;
049: _jdbcProps = jdbcProps;
050: }
051:
052: Connection getConnection() throws NamingException, SQLException {
053: Connection conn;
054: if (_datasource != null) {
055: Context ctx = new InitialContext();
056: conn = ((DataSource) ctx.lookup(_datasource))
057: .getConnection();
058: } else {
059: try {
060: Class.forName(_driver).newInstance();
061: } catch (Exception ex) {
062: throw new RuntimeException("JDBC driver not loaded", ex);
063: }
064: conn = DriverManager.getConnection(_jdbcUrl, _jdbcProps);
065: }
066: return conn;
067: }
068:
069: /**
070: * Executes a SQLTask run() method giving a live JDBC connection to it.
071: * <p>
072: * The SQLTask run() method should not close the connection, the connection will
073: * be recycled by the SQLExecutorImpl.
074: * <p>
075: * If using a transaction and the transaction is not committed
076: * within the SQLTask run() method, the transaction will be rolled back by
077: * the SQLExecutorImpl.
078: * <p>
079: * @param task SQLTask to invoke the run() method.
080: * @throws java.sql.SQLException thrown if there uncaught SQLException in the SQLTask run() method or if
081: * the JDBC connection could not be recycled properly.
082: *
083: */
084: public void execute(SQLTask task) throws SQLException,
085: RepoException {
086: ParameterCheck.checkNotNull("task", task);
087: Connection conn = null;
088: try {
089: if (_logger.isLoggable(Level.FINER)) {
090: _logger.log(Level.FINER, "SQLTask.run() begins, "
091: + task.getClass().getName());
092: }
093: conn = getConnection();
094: task.run(conn);
095: if (_logger.isLoggable(Level.FINER)) {
096: _logger.log(Level.FINER, "SQLTask.run() ends, "
097: + task.getClass().getName());
098: }
099: } catch (NamingException ex) {
100: _logger.log(Level.WARNING, "SQLTask.run() datasource '"
101: + _datasource + "' exception, "
102: + task.getClass().getName(), ex);
103: throw new RuntimeException(ex);
104:
105: } catch (SQLException ex) {
106: _logger.log(Level.WARNING, "SQLTask.run() exception, "
107: + task.getClass().getName(), ex);
108: throw ex;
109: } finally {
110: try {
111: if (conn != null && !conn.isClosed()) {
112: conn.close();
113: }
114: } catch (SQLException ex) {
115: _logger.log(Level.WARNING,
116: "exception recycling connection, "
117: + task.getClass().getName(), ex);
118: }
119: }
120: }
121:
122: }
|