001/*
002 * Copyright 2002-2013 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.sql.Connection;
021import java.sql.SQLException;
022
023import org.springframework.util.ReflectionUtils;
024
025/**
026 * Implementation of the {@link NativeJdbcExtractor} interface for WebSphere,
027 * supporting WebSphere Application Server 6.1 and higher.
028 *
029 * <p>Returns the underlying native Connection to application code instead
030 * of WebSphere's wrapper implementation; unwraps the Connection for
031 * native statements. The returned JDBC classes can then safely be cast,
032 * e.g. to {@code oracle.jdbc.OracleConnection}.
033 *
034 * <p>This NativeJdbcExtractor can be set just to <i>allow</i> working
035 * with a WebSphere DataSource: If a given object is not a WebSphere
036 * Connection wrapper, it will be returned as-is.
037 *
038 * @author Juergen Hoeller
039 * @since 1.1
040 */
041public class WebSphereNativeJdbcExtractor extends NativeJdbcExtractorAdapter {
042
043        private static final String JDBC_ADAPTER_CONNECTION_NAME = "com.ibm.ws.rsadapter.jdbc.WSJdbcConnection";
044
045        private static final String JDBC_ADAPTER_UTIL_NAME = "com.ibm.ws.rsadapter.jdbc.WSJdbcUtil";
046
047
048        private Class<?> webSphereConnectionClass;
049
050        private Method webSphereNativeConnectionMethod;
051
052
053        /**
054         * This constructor retrieves WebSphere JDBC adapter classes,
055         * so we can get the underlying vendor connection using reflection.
056         */
057        public WebSphereNativeJdbcExtractor() {
058                try {
059                        this.webSphereConnectionClass = getClass().getClassLoader().loadClass(JDBC_ADAPTER_CONNECTION_NAME);
060                        Class<?> jdbcAdapterUtilClass = getClass().getClassLoader().loadClass(JDBC_ADAPTER_UTIL_NAME);
061                        this.webSphereNativeConnectionMethod =
062                                        jdbcAdapterUtilClass.getMethod("getNativeConnection", new Class<?>[] {this.webSphereConnectionClass});
063                }
064                catch (Exception ex) {
065                        throw new IllegalStateException(
066                                        "Could not initialize WebSphereNativeJdbcExtractor because WebSphere API classes are not available: " + ex);
067                }
068        }
069
070
071        /**
072         * Return {@code true}, as WebSphere returns wrapped Statements.
073         */
074        @Override
075        public boolean isNativeConnectionNecessaryForNativeStatements() {
076                return true;
077        }
078
079        /**
080         * Return {@code true}, as WebSphere returns wrapped PreparedStatements.
081         */
082        @Override
083        public boolean isNativeConnectionNecessaryForNativePreparedStatements() {
084                return true;
085        }
086
087        /**
088         * Return {@code true}, as WebSphere returns wrapped CallableStatements.
089         */
090        @Override
091        public boolean isNativeConnectionNecessaryForNativeCallableStatements() {
092                return true;
093        }
094
095        /**
096         * Retrieve the Connection via WebSphere's {@code getNativeConnection} method.
097         */
098        @Override
099        protected Connection doGetNativeConnection(Connection con) throws SQLException {
100                if (this.webSphereConnectionClass.isAssignableFrom(con.getClass())) {
101                        return (Connection) ReflectionUtils.invokeJdbcMethod(this.webSphereNativeConnectionMethod, null, con);
102                }
103                return con;
104        }
105
106}