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 org.apache.commons.logging.Log;
024: import org.apache.commons.logging.LogFactory;
025:
026: import org.springframework.util.ReflectionUtils;
027:
028: /**
029: * Implementation of the NativeJdbcExtractor interface for WebSphere.
030: *
031: * <p>Returns the underlying native Connection to application code instead
032: * of WebSphere's wrapper implementation; unwraps the Connection for
033: * native statements. The returned JDBC classes can then safely be cast,
034: * e.g. to <code>oracle.jdbc.OracleConnection</code>.
035: *
036: * <p>This NativeJdbcExtractor can be set just to <i>allow</i> working
037: * with a WebSphere DataSource: If a given object is not a WebSphere
038: * Connection wrapper, it will be returned as-is.
039: *
040: * <p>Supports both WebSphere 5 and WebSphere 4. Currently tested with
041: * IBM WebSphere 5.1.0, 5.0.2 and 4.0.6. Thanks to Dave Keller and Victor
042: * for figuring out how to do the unwrapping on WebSphere 5 and 4!
043: *
044: * @author Juergen Hoeller
045: * @since 1.1
046: * @see com.ibm.ws.rsadapter.jdbc.WSJdbcConnection
047: * @see com.ibm.ws.rsadapter.jdbc.WSJdbcUtil#getNativeConnection
048: * @see com.ibm.ejs.cm.proxy.ConnectionProxy#getPhysicalConnection
049: */
050: public class WebSphereNativeJdbcExtractor extends
051: NativeJdbcExtractorAdapter {
052:
053: private static final String JDBC_ADAPTER_CONNECTION_NAME_5 = "com.ibm.ws.rsadapter.jdbc.WSJdbcConnection";
054:
055: private static final String JDBC_ADAPTER_UTIL_NAME_5 = "com.ibm.ws.rsadapter.jdbc.WSJdbcUtil";
056:
057: private static final String CONNECTION_PROXY_NAME_4 = "com.ibm.ejs.cm.proxy.ConnectionProxy";
058:
059: protected final Log logger = LogFactory.getLog(getClass());
060:
061: private Class webSphere5ConnectionClass;
062:
063: private Class webSphere4ConnectionClass;
064:
065: private Method webSphere5NativeConnectionMethod;
066:
067: private Method webSphere4PhysicalConnectionMethod;
068:
069: /**
070: * This constructor retrieves WebSphere JDBC adapter classes,
071: * so we can get the underlying vendor connection using reflection.
072: */
073: public WebSphereNativeJdbcExtractor() {
074: // Detect WebSphere 5 connection classes.
075: try {
076: logger.debug("Trying WebSphere 5 Connection: "
077: + JDBC_ADAPTER_CONNECTION_NAME_5);
078: this .webSphere5ConnectionClass = getClass()
079: .getClassLoader().loadClass(
080: JDBC_ADAPTER_CONNECTION_NAME_5);
081: Class jdbcAdapterUtilClass = getClass().getClassLoader()
082: .loadClass(JDBC_ADAPTER_UTIL_NAME_5);
083: this .webSphere5NativeConnectionMethod = jdbcAdapterUtilClass
084: .getMethod(
085: "getNativeConnection",
086: new Class[] { this .webSphere5ConnectionClass });
087: } catch (Exception ex) {
088: logger
089: .debug(
090: "Could not find WebSphere 5 connection pool classes",
091: ex);
092: }
093:
094: // Detect WebSphere 4 connection classes.
095: // Might also be found on WebSphere 5, for version 4 DataSources.
096: try {
097: logger.debug("Trying WebSphere 4 Connection: "
098: + CONNECTION_PROXY_NAME_4);
099: this .webSphere4ConnectionClass = getClass()
100: .getClassLoader()
101: .loadClass(CONNECTION_PROXY_NAME_4);
102: this .webSphere4PhysicalConnectionMethod = this .webSphere4ConnectionClass
103: .getMethod("getPhysicalConnection", (Class[]) null);
104: } catch (Exception ex) {
105: logger
106: .debug(
107: "Could not find WebSphere 4 connection pool classes",
108: ex);
109: }
110: }
111:
112: /**
113: * Return <code>true</code>, as WebSphere returns wrapped Statements.
114: */
115: public boolean isNativeConnectionNecessaryForNativeStatements() {
116: return true;
117: }
118:
119: /**
120: * Return <code>true</code>, as WebSphere returns wrapped PreparedStatements.
121: */
122: public boolean isNativeConnectionNecessaryForNativePreparedStatements() {
123: return true;
124: }
125:
126: /**
127: * Return <code>true</code>, as WebSphere returns wrapped CallableStatements.
128: */
129: public boolean isNativeConnectionNecessaryForNativeCallableStatements() {
130: return true;
131: }
132:
133: /**
134: * Retrieve the Connection via WebSphere's <code>getNativeConnection</code> method.
135: */
136: protected Connection doGetNativeConnection(Connection con)
137: throws SQLException {
138: // WebSphere 5 connection?
139: if (this .webSphere5ConnectionClass != null
140: && this .webSphere5ConnectionClass.isAssignableFrom(con
141: .getClass())) {
142: // WebSphere 5's WSJdbcUtil.getNativeConnection(wsJdbcConnection)
143: return (Connection) ReflectionUtils.invokeMethod(
144: this .webSphere5NativeConnectionMethod, null,
145: new Object[] { con });
146: }
147:
148: // WebSphere 4 connection (or version 4 connection on WebSphere 5)?
149: else if (this .webSphere4ConnectionClass != null
150: && this .webSphere4ConnectionClass.isAssignableFrom(con
151: .getClass())) {
152: // WebSphere 4's connectionProxy.getPhysicalConnection()
153: return (Connection) ReflectionUtils.invokeMethod(
154: this .webSphere4PhysicalConnectionMethod, con);
155: }
156:
157: // No known WebSphere connection -> return as-is.
158: else {
159: if (logger.isDebugEnabled()) {
160: logger
161: .debug("Connection ["
162: + con
163: + "] is not a WebSphere 5/4 connection, returning as-is");
164: }
165: return con;
166: }
167: }
168:
169: }
|