001: /*
002: JSPWiki - a JSP-based WikiWiki clone.
003:
004: Copyright (C) 2004-2005 Xan Gregg (xan.gregg@forthgo.com)
005:
006: This program is free software; you can redistribute it and/or modify
007: it under the terms of the GNU Lesser General Public License as published by
008: the Free Software Foundation; either version 2.1 of the License, or
009: (at your option) any later version.
010:
011: This program is distributed in the hope that it will be useful,
012: but WITHOUT ANY WARRANTY; without even the implied warranty of
013: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: GNU Lesser General Public License for more details.
015:
016: You should have received a copy of the GNU Lesser General Public License
017: along with this program; if not, write to the Free Software
018: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: */
020: package com.forthgo.jspwiki.jdbcprovider;
021:
022: import com.ecyrd.jspwiki.NoRequiredPropertyException;
023: import com.ecyrd.jspwiki.TextUtil;
024: import com.ecyrd.jspwiki.WikiEngine;
025: import org.apache.log4j.Category;
026:
027: import java.io.IOException;
028: import java.sql.*;
029: import java.util.Properties;
030:
031: import javax.naming.Context;
032: import javax.naming.InitialContext;
033: import javax.naming.NamingException;
034: import javax.sql.DataSource;
035:
036: /*
037: * History:
038: * 2006-02-10 SU Use JNDI DataSource to create database connection.
039: * Got rid of using CoreConnectionPool class.
040: * Pooling can take place in webcontainer or jdbc driver.
041: * 2005-09-28 XG Made default number of cached connections be 0 after seeing resource
042: * problems with other values on Linux.
043: * 2005-08-30 XG Fixed bug: was using wrong property name for cached connection setting.
044: */
045:
046: /**
047: * An abstract base class for JDBC-based providers.
048: */
049: public abstract class JDBCBaseProvider {
050:
051: public void initialize(WikiEngine engine, Properties properties)
052: throws NoRequiredPropertyException, IOException {
053: try {
054: checkConnection();
055: } catch (SQLException e) {
056: throw new IOException("SQL Exception: " + e.getMessage());
057: }
058: }
059:
060: private String getRequired(Properties properties, String name)
061: throws NoRequiredPropertyException {
062: return WikiEngine.getRequiredProperty(properties,
063: getPropertyBase() + name);
064: }
065:
066: /**
067: * Returns a string to use as a prefix for property names.
068: *
069: * @return property name prefix
070: */
071: protected abstract String getPropertyBase();
072:
073: public abstract Category getLog();
074:
075: protected void debug(String message) {
076: getLog().debug(message);
077: }
078:
079: protected void info(String message) {
080: getLog().info(message);
081: }
082:
083: protected void error(String message, Throwable t) {
084: getLog().error(message, t);
085: }
086:
087: private void checkConnection() throws SQLException {
088: Connection connection = null;
089: try {
090: connection = getConnection();
091: } catch (SQLException e) {
092: error("Unable to get database connection", e);
093: throw e;
094: } finally {
095: releaseConnection(connection);
096: }
097: }
098:
099: public boolean isConnectionOK(Connection connection) {
100: try {
101: String sql = "SELECT 1 FROM " + getCheckAliveTableName();
102: Statement stmt = connection.createStatement();
103: ResultSet rs = stmt.executeQuery(sql);
104: rs.close();
105: stmt.close();
106: } catch (SQLException se) {
107: return false;
108: }
109: return true;
110: }
111:
112: public abstract String getCheckAliveTableName();
113:
114: protected Connection getConnection() throws SQLException {
115: String datasource = "java:comp/env/jdbc/WikiDB";
116: Connection conn = null;
117: try {
118: Context ctx = new InitialContext();
119: conn = ((DataSource) ctx.lookup(datasource))
120: .getConnection();
121: } catch (NamingException ne) {
122: error("exception looking up datasource name=" + datasource,
123: ne);
124: throw new RuntimeException(
125: "JDBCBaseProvider.getConnection(): Failed to look up datasource="
126: + datasource, ne);
127: }
128:
129: return conn;
130: }
131:
132: protected void releaseConnection(Connection connection) {
133: if (connection == null)
134: return; // happens if we are called in a finally clause of a failed getConnection
135: try {
136: if (connection != null && !connection.isClosed()) {
137: connection.close();
138: }
139: } catch (SQLException e) {
140: error("connection failed to close", e);
141: }
142: }
143:
144: /**
145: * Checks that a table by the given name exists.
146: *
147: * @param tableName the sql table name
148: * @throws SQLException if the table query fails
149: */
150: protected void checkTable(String tableName) throws SQLException {
151: Connection connection = null;
152: try {
153: connection = getConnection();
154: String sql = "SELECT COUNT(*) FROM " + tableName;
155: Statement stmt = connection.createStatement();
156: ResultSet rs = stmt.executeQuery(sql);
157: rs.close();
158: stmt.close();
159: } catch (SQLException se) {
160: error("Unable to find the table: " + tableName, se);
161: throw se;
162: } finally {
163: releaseConnection(connection);
164: }
165: }
166: }
|