001: /*
002: * Copyright 2002-2006 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.jdbc.support.nativejdbc;
018:
019: import java.lang.reflect.Method;
020: import java.lang.reflect.Modifier;
021: import java.sql.CallableStatement;
022: import java.sql.Connection;
023: import java.sql.PreparedStatement;
024: import java.sql.ResultSet;
025: import java.sql.SQLException;
026: import java.sql.Statement;
027:
028: import org.springframework.util.ReflectionUtils;
029:
030: /**
031: * Implementation of the NativeJdbcExtractor interface for the
032: * Jakarta Commons DBCP connection pool.
033: *
034: * <p>Returns the underlying native Connection, Statement, etc to application
035: * code instead of DBCP's wrapper implementations. The returned JDBC classes
036: * can then safely be cast, e.g. to <code>oracle.jdbc.OracleConnection</code>.
037: *
038: * <p>This NativeJdbcExtractor can be set just to <i>allow</i> working with a
039: * Commons DBCP DataSource: If a given object is not a Commons DBCP wrapper,
040: * it will be returned as-is.
041: *
042: * <p>Tested against Commons DBCP 1.1 and 1.2, but should also work with 1.0.
043: * Before Commons DBCP 1.1, DelegatingCallableStatement and DelegatingResultSet
044: * have not offered any means to access underlying delegates: As a consequence,
045: * <code>getNativeCallableStatement</code> and <code>getNativeResultSet</code>
046: * will not work with Commons DBCP 1.0.
047: *
048: * <p>Note that this version of CommonsDbcpNativeJdbcExtractor will work
049: * against the original Commons DBCP in <code>org.apache.commons.dbcp</code>
050: * as well as against Tomcat 5.5's relocated Commons DBCP version in the
051: * <code>org.apache.tomcat.dbcp.dbcp</code> package.
052: *
053: * @author Juergen Hoeller
054: * @since 25.08.2003
055: */
056: public class CommonsDbcpNativeJdbcExtractor extends
057: NativeJdbcExtractorAdapter {
058:
059: private static final String GET_INNERMOST_DELEGATE_METHOD_NAME = "getInnermostDelegate";
060:
061: /**
062: * Extracts the innermost delegate from the given Commons DBCP object.
063: * Falls back to the given object if no underlying object found.
064: * @param obj the Commons DBCP Connection/Statement/ResultSet
065: * @return the underlying native Connection/Statement/ResultSet
066: */
067: private static Object getInnermostDelegate(Object obj) {
068: if (obj == null) {
069: return null;
070: }
071: try {
072: Class classToAnalyze = obj.getClass();
073: while (!Modifier.isPublic(classToAnalyze.getModifiers())) {
074: classToAnalyze = classToAnalyze.getSuperclass();
075: if (classToAnalyze == null) {
076: // No public provider class found -> fall back to given object.
077: return obj;
078: }
079: }
080: Method getInnermostDelegate = classToAnalyze.getMethod(
081: GET_INNERMOST_DELEGATE_METHOD_NAME, (Class[]) null);
082: Object delegate = ReflectionUtils.invokeMethod(
083: getInnermostDelegate, obj);
084: return (delegate != null ? delegate : obj);
085: } catch (NoSuchMethodException ex) {
086: return obj;
087: } catch (SecurityException ex) {
088: throw new IllegalStateException(
089: "Commons DBCP getInnermostDelegate method is not accessible: "
090: + ex);
091: }
092: }
093:
094: protected Connection doGetNativeConnection(Connection con)
095: throws SQLException {
096: return (Connection) getInnermostDelegate(con);
097: }
098:
099: public Statement getNativeStatement(Statement stmt)
100: throws SQLException {
101: return (Statement) getInnermostDelegate(stmt);
102: }
103:
104: public PreparedStatement getNativePreparedStatement(
105: PreparedStatement ps) throws SQLException {
106: return (PreparedStatement) getNativeStatement(ps);
107: }
108:
109: public CallableStatement getNativeCallableStatement(
110: CallableStatement cs) throws SQLException {
111: return (CallableStatement) getNativeStatement(cs);
112: }
113:
114: public ResultSet getNativeResultSet(ResultSet rs)
115: throws SQLException {
116: return (ResultSet) getInnermostDelegate(rs);
117: }
118:
119: }
|