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