001: /****************************************************************
002: * Licensed to the Apache Software Foundation (ASF) under one *
003: * or more contributor license agreements. See the NOTICE file *
004: * distributed with this work for additional information *
005: * regarding copyright ownership. The ASF licenses this file *
006: * to you under the Apache License, Version 2.0 (the *
007: * "License"); you may not use this file except in compliance *
008: * with the License. You may obtain a copy of the License at *
009: * *
010: * http://www.apache.org/licenses/LICENSE-2.0 *
011: * *
012: * Unless required by applicable law or agreed to in writing, *
013: * software distributed under the License is distributed on an *
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
015: * KIND, either express or implied. See the License for the *
016: * specific language governing permissions and limitations *
017: * under the License. *
018: ****************************************************************/package org.apache.james.util;
019:
020: import java.sql.Connection;
021: import java.sql.DatabaseMetaData;
022: import java.sql.ResultSet;
023: import java.sql.SQLException;
024: import java.sql.Statement;
025: import java.util.Locale;
026:
027: /**
028: * <p>Helper class for managing common JDBC tasks.</p>
029: *
030: * <p>This class is abstract to allow implementations to
031: * take advantage of different logging capabilities/interfaces in
032: * different parts of the code.</p>
033: *
034: * @version CVS $Revision: 494012 $ $Date: 2007-01-08 11:23:58 +0100 (Mo, 08 Jan 2007) $
035: */
036: abstract public class JDBCUtil {
037: /**
038: * An abstract method which child classes override to handle logging of
039: * errors in their particular environments.
040: *
041: * @param errorString the error message generated
042: */
043: abstract protected void delegatedLog(String errorString);
044:
045: /**
046: * Checks database metadata to see if a table exists.
047: * Try UPPER, lower, and MixedCase, to see if the table is there.
048: *
049: * @param dbMetaData the database metadata to be used to look up this table
050: * @param tableName the table name
051: *
052: * @throws SQLException if an exception is encountered while accessing the database
053: */
054: public boolean tableExists(DatabaseMetaData dbMetaData,
055: String tableName) throws SQLException {
056: return (tableExistsCaseSensitive(dbMetaData, tableName)
057: || tableExistsCaseSensitive(dbMetaData, tableName
058: .toUpperCase(Locale.US)) || tableExistsCaseSensitive(
059: dbMetaData, tableName.toLowerCase(Locale.US)));
060: }
061:
062: /**
063: * Checks database metadata to see if a table exists. This method
064: * is sensitive to the case of the provided table name.
065: *
066: * @param dbMetaData the database metadata to be used to look up this table
067: * @param tableName the case sensitive table name
068: *
069: * @throws SQLException if an exception is encountered while accessing the database
070: */
071: public boolean tableExistsCaseSensitive(
072: DatabaseMetaData dbMetaData, String tableName)
073: throws SQLException {
074: ResultSet rsTables = dbMetaData.getTables(null, null,
075: tableName, null);
076: try {
077: boolean found = rsTables.next();
078: return found;
079: } finally {
080: closeJDBCResultSet(rsTables);
081: }
082: }
083:
084: /**
085: * Checks database metadata to see if a column exists in a table
086: * Try UPPER, lower, and MixedCase, both on the table name and the column name, to see if the column is there.
087: *
088: * @param dbMetaData the database metadata to be used to look up this column
089: * @param tableName the table name
090: * @param columnName the column name
091: *
092: * @throws SQLException if an exception is encountered while accessing the database
093: */
094: public boolean columnExists(DatabaseMetaData dbMetaData,
095: String tableName, String columnName) throws SQLException {
096: return (columnExistsCaseSensitive(dbMetaData, tableName,
097: columnName)
098: || columnExistsCaseSensitive(dbMetaData, tableName,
099: columnName.toUpperCase(Locale.US))
100: || columnExistsCaseSensitive(dbMetaData, tableName,
101: columnName.toLowerCase(Locale.US))
102: || columnExistsCaseSensitive(dbMetaData, tableName
103: .toUpperCase(Locale.US), columnName)
104: || columnExistsCaseSensitive(dbMetaData, tableName
105: .toUpperCase(Locale.US), columnName
106: .toUpperCase(Locale.US))
107: || columnExistsCaseSensitive(dbMetaData, tableName
108: .toUpperCase(Locale.US), columnName
109: .toLowerCase(Locale.US))
110: || columnExistsCaseSensitive(dbMetaData, tableName
111: .toLowerCase(Locale.US), columnName)
112: || columnExistsCaseSensitive(dbMetaData, tableName
113: .toLowerCase(Locale.US), columnName
114: .toUpperCase(Locale.US)) || columnExistsCaseSensitive(
115: dbMetaData, tableName.toLowerCase(Locale.US),
116: columnName.toLowerCase(Locale.US)));
117: }
118:
119: /**
120: * Checks database metadata to see if a column exists in a table. This method
121: * is sensitive to the case of both the provided table name and column name.
122: *
123: * @param dbMetaData the database metadata to be used to look up this column
124: * @param tableName the case sensitive table name
125: * @param columnName the case sensitive column name
126: *
127: * @throws SQLException if an exception is encountered while accessing the database
128: */
129: public boolean columnExistsCaseSensitive(
130: DatabaseMetaData dbMetaData, String tableName,
131: String columnName) throws SQLException {
132: ResultSet rsTables = dbMetaData.getColumns(null, null,
133: tableName, columnName);
134: try {
135: boolean found = rsTables.next();
136: return found;
137: } finally {
138: closeJDBCResultSet(rsTables);
139: }
140: }
141:
142: /**
143: * Closes database connection and logs if an error
144: * is encountered
145: *
146: * @param conn the connection to be closed
147: */
148: public void closeJDBCConnection(Connection conn) {
149: try {
150: if (conn != null) {
151: conn.close();
152: }
153: } catch (SQLException sqle) {
154: // Log exception and continue
155: subclassLogWrapper("Unexpected exception while closing database connection.");
156: }
157: }
158:
159: /**
160: * Closes database statement and logs if an error
161: * is encountered
162: *
163: * @param stmt the statement to be closed
164: */
165: public void closeJDBCStatement(Statement stmt) {
166: try {
167: if (stmt != null) {
168: stmt.close();
169: }
170: } catch (SQLException sqle) {
171: // Log exception and continue
172: subclassLogWrapper("Unexpected exception while closing database statement.");
173: }
174: }
175:
176: /**
177: * Closes database result set and logs if an error
178: * is encountered
179: *
180: * @param aResultSet the result set to be closed
181: */
182: public void closeJDBCResultSet(ResultSet aResultSet) {
183: try {
184: if (aResultSet != null) {
185: aResultSet.close();
186: }
187: } catch (SQLException sqle) {
188: // Log exception and continue
189: subclassLogWrapper("Unexpected exception while closing database result set.");
190: }
191: }
192:
193: /**
194: * Wraps the delegated call to the subclass logging method with a Throwable
195: * wrapper. All throwables generated by the subclass logging method are
196: * caught and ignored.
197: *
198: * @param logString the raw string to be passed to the logging method implemented
199: * by the subclass
200: */
201: private void subclassLogWrapper(String logString) {
202: try {
203: delegatedLog(logString);
204: } catch (Throwable t) {
205: // Throwables generated by the logging system are ignored
206: }
207: }
208:
209: }
|