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.sql.Connection;
021: import java.sql.SQLException;
022:
023: import com.mchange.v2.c3p0.C3P0ProxyConnection;
024:
025: import org.springframework.util.ReflectionUtils;
026:
027: /**
028: * Implementation of the NativeJdbcExtractor interface for the C3P0 connection pool.
029: *
030: * <p>Returns underlying native Connections to application code instead of C3P0's
031: * wrapper implementations; unwraps the Connection for native Statements.
032: * The returned JDBC classes can then safely be cast, e.g. to
033: * <code>oracle.jdbc.OracleConnection</code>.
034: *
035: * <p>This NativeJdbcExtractor can be set just to <i>allow</i> working with
036: * a C3P0 DataSource: If a given object is not a C3P0 wrapper, it will be
037: * returned as-is.
038: *
039: * <p>Note that this class requires C3P0 0.8.5 or later; for earlier C3P0 versions,
040: * use SimpleNativeJdbcExtractor (which won't work for C3P0 0.8.5 or later).
041: *
042: * @author Juergen Hoeller
043: * @since 1.1.5
044: * @see com.mchange.v2.c3p0.C3P0ProxyConnection#rawConnectionOperation
045: * @see SimpleNativeJdbcExtractor
046: */
047: public class C3P0NativeJdbcExtractor extends NativeJdbcExtractorAdapter {
048:
049: private final Method getRawConnectionMethod;
050:
051: /**
052: * This method is not meant to be used directly; it rather serves
053: * as callback method for C3P0's "rawConnectionOperation" API.
054: * @param con a native Connection handle
055: * @return the native Connection handle, as-is
056: */
057: public static Connection getRawConnection(Connection con) {
058: return con;
059: }
060:
061: public C3P0NativeJdbcExtractor() {
062: try {
063: this .getRawConnectionMethod = getClass().getMethod(
064: "getRawConnection",
065: new Class[] { Connection.class });
066: } catch (NoSuchMethodException ex) {
067: throw new IllegalStateException(
068: "Internal error in C3P0NativeJdbcExtractor: "
069: + ex.getMessage());
070: }
071: }
072:
073: public boolean isNativeConnectionNecessaryForNativeStatements() {
074: return true;
075: }
076:
077: public boolean isNativeConnectionNecessaryForNativePreparedStatements() {
078: return true;
079: }
080:
081: public boolean isNativeConnectionNecessaryForNativeCallableStatements() {
082: return true;
083: }
084:
085: /**
086: * Retrieve the Connection via C3P0's <code>rawConnectionOperation</code> API,
087: * using the <code>getRawConnection</code> as callback to get access to the
088: * raw Connection (which is otherwise not directly supported by C3P0).
089: * @see #getRawConnection
090: */
091: protected Connection doGetNativeConnection(Connection con)
092: throws SQLException {
093: if (con instanceof C3P0ProxyConnection) {
094: C3P0ProxyConnection cpCon = (C3P0ProxyConnection) con;
095: try {
096: return (Connection) cpCon
097: .rawConnectionOperation(
098: this .getRawConnectionMethod,
099: null,
100: new Object[] { C3P0ProxyConnection.RAW_CONNECTION });
101: } catch (SQLException ex) {
102: throw ex;
103: } catch (Exception ex) {
104: ReflectionUtils.handleReflectionException(ex);
105: }
106: }
107: return con;
108: }
109:
110: }
|