001/* 002 * Copyright 2002-2015 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 * https://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 017package org.springframework.jdbc.support.nativejdbc; 018 019import java.lang.reflect.Method; 020import java.lang.reflect.Modifier; 021import java.sql.CallableStatement; 022import java.sql.Connection; 023import java.sql.PreparedStatement; 024import java.sql.ResultSet; 025import java.sql.SQLException; 026import java.sql.Statement; 027 028import org.springframework.util.ReflectionUtils; 029 030/** 031 * Implementation of the {@link NativeJdbcExtractor} interface for the 032 * Apache Commons DBCP connection pool, version 1.1 or higher. 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}. 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>Note that this version of CommonsDbcpNativeJdbcExtractor will work 043 * against the original Commons DBCP in {@code org.apache.commons.dbcp} 044 * as well as against Tomcat 5.5's relocated Commons DBCP version in the 045 * {@code org.apache.tomcat.dbcp.dbcp} package. 046 * 047 * @author Juergen Hoeller 048 * @since 25.08.2003 049 * @deprecated as of Spring 4.2, in favor of Commons DBCP 2.x and JDBC 4.x 050 */ 051@Deprecated 052public class CommonsDbcpNativeJdbcExtractor extends NativeJdbcExtractorAdapter { 053 054 private static final String GET_INNERMOST_DELEGATE_METHOD_NAME = "getInnermostDelegate"; 055 056 057 /** 058 * Extracts the innermost delegate from the given Commons DBCP object. 059 * Falls back to the given object if no underlying object found. 060 * @param obj the Commons DBCP Connection/Statement/ResultSet 061 * @return the underlying native Connection/Statement/ResultSet 062 */ 063 private static Object getInnermostDelegate(Object obj) throws SQLException { 064 if (obj == null) { 065 return null; 066 } 067 try { 068 Class<?> classToAnalyze = obj.getClass(); 069 while (!Modifier.isPublic(classToAnalyze.getModifiers())) { 070 classToAnalyze = classToAnalyze.getSuperclass(); 071 if (classToAnalyze == null) { 072 // No public provider class found -> fall back to given object. 073 return obj; 074 } 075 } 076 Method getInnermostDelegate = classToAnalyze.getMethod(GET_INNERMOST_DELEGATE_METHOD_NAME, (Class[]) null); 077 Object delegate = ReflectionUtils.invokeJdbcMethod(getInnermostDelegate, obj); 078 return (delegate != null ? delegate : obj); 079 } 080 catch (NoSuchMethodException ex) { 081 return obj; 082 } 083 catch (SecurityException ex) { 084 throw new IllegalStateException("Commons DBCP getInnermostDelegate method is not accessible: " + ex); 085 } 086 } 087 088 089 @Override 090 protected Connection doGetNativeConnection(Connection con) throws SQLException { 091 return (Connection) getInnermostDelegate(con); 092 } 093 094 @Override 095 public Statement getNativeStatement(Statement stmt) throws SQLException { 096 return (Statement) getInnermostDelegate(stmt); 097 } 098 099 @Override 100 public PreparedStatement getNativePreparedStatement(PreparedStatement ps) throws SQLException { 101 return (PreparedStatement) getNativeStatement(ps); 102 } 103 104 @Override 105 public CallableStatement getNativeCallableStatement(CallableStatement cs) throws SQLException { 106 return (CallableStatement) getNativeStatement(cs); 107 } 108 109 @Override 110 public ResultSet getNativeResultSet(ResultSet rs) throws SQLException { 111 return (ResultSet) getInnermostDelegate(rs); 112 } 113 114}