/* * Copyright 2002-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.jdbc.support.nativejdbc; import java.lang.reflect.Method; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import org.springframework.util.ReflectionUtils; /** * Implementation of the {@link NativeJdbcExtractor} interface for JBoss, * supporting JBoss Application Server 3.2.4+. As of Spring 3.1.1, it also * supports JBoss 7. * * <p>Returns the underlying native Connection, Statement, etc to * application code instead of JBoss' wrapper implementations. * The returned JDBC classes can then safely be cast, e.g. to * {@code oracle.jdbc.OracleConnection}. * * <p>This NativeJdbcExtractor can be set just to <i>allow</i> working with * a JBoss connection pool: If a given object is not a JBoss wrapper, * it will be returned as-is. * * @author Juergen Hoeller * @since 03.01.2004 * @see org.jboss.resource.adapter.jdbc.WrappedConnection#getUnderlyingConnection * @see org.jboss.resource.adapter.jdbc.WrappedStatement#getUnderlyingStatement * @see org.jboss.resource.adapter.jdbc.WrappedResultSet#getUnderlyingResultSet */ public class JBossNativeJdbcExtractor extends NativeJdbcExtractorAdapter { // JBoss 7 private static final String JBOSS_JCA_PREFIX = "org.jboss.jca.adapters.jdbc."; // JBoss <= 6 private static final String JBOSS_RESOURCE_PREFIX = "org.jboss.resource.adapter.jdbc."; private Class<?> wrappedConnectionClass; private Class<?> wrappedStatementClass; private Class<?> wrappedResultSetClass; private Method getUnderlyingConnectionMethod; private Method getUnderlyingStatementMethod; private Method getUnderlyingResultSetMethod; /** * This constructor retrieves JBoss JDBC wrapper classes, * so we can get the underlying vendor connection using reflection. */ public JBossNativeJdbcExtractor() { String prefix = JBOSS_JCA_PREFIX; try { // trying JBoss 7 jca package first... this.wrappedConnectionClass = getClass().getClassLoader().loadClass(prefix + "WrappedConnection"); } catch (ClassNotFoundException ex) { // JBoss 7 jca package not found -> try traditional resource package. prefix = JBOSS_RESOURCE_PREFIX; try { this.wrappedConnectionClass = getClass().getClassLoader().loadClass(prefix + "WrappedConnection"); } catch (ClassNotFoundException ex2) { throw new IllegalStateException("Could not initialize JBossNativeJdbcExtractor: neither JBoss 7's [" + JBOSS_JCA_PREFIX + ".WrappedConnection] nor traditional JBoss [" + JBOSS_RESOURCE_PREFIX + ".WrappedConnection] found"); } } try { this.wrappedStatementClass = getClass().getClassLoader().loadClass(prefix + "WrappedStatement"); this.wrappedResultSetClass = getClass().getClassLoader().loadClass(prefix + "WrappedResultSet"); this.getUnderlyingConnectionMethod = this.wrappedConnectionClass.getMethod("getUnderlyingConnection", (Class[]) null); this.getUnderlyingStatementMethod = this.wrappedStatementClass.getMethod("getUnderlyingStatement", (Class[]) null); this.getUnderlyingResultSetMethod = this.wrappedResultSetClass.getMethod("getUnderlyingResultSet", (Class[]) null); } catch (Exception ex) { throw new IllegalStateException( "Could not initialize JBossNativeJdbcExtractor because of missing JBoss API methods/classes: " + ex); } } /** * Retrieve the Connection via JBoss' {@code getUnderlyingConnection} method. */ @Override protected Connection doGetNativeConnection(Connection con) throws SQLException { if (this.wrappedConnectionClass.isAssignableFrom(con.getClass())) { return (Connection) ReflectionUtils.invokeJdbcMethod(this.getUnderlyingConnectionMethod, con); } return con; } /** * Retrieve the Connection via JBoss' {@code getUnderlyingStatement} method. */ @Override public Statement getNativeStatement(Statement stmt) throws SQLException { if (this.wrappedStatementClass.isAssignableFrom(stmt.getClass())) { return (Statement) ReflectionUtils.invokeJdbcMethod(this.getUnderlyingStatementMethod, stmt); } return stmt; } /** * Retrieve the Connection via JBoss' {@code getUnderlyingStatement} method. */ @Override public PreparedStatement getNativePreparedStatement(PreparedStatement ps) throws SQLException { return (PreparedStatement) getNativeStatement(ps); } /** * Retrieve the Connection via JBoss' {@code getUnderlyingStatement} method. */ @Override public CallableStatement getNativeCallableStatement(CallableStatement cs) throws SQLException { return (CallableStatement) getNativeStatement(cs); } /** * Retrieve the Connection via JBoss' {@code getUnderlyingResultSet} method. */ @Override public ResultSet getNativeResultSet(ResultSet rs) throws SQLException { if (this.wrappedResultSetClass.isAssignableFrom(rs.getClass())) { return (ResultSet) ReflectionUtils.invokeJdbcMethod(this.getUnderlyingResultSetMethod, rs); } return rs; } }