KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > jdbc > datasource > WebSphereDataSourceAdapter


1 /*
2  * Copyright 2002-2007 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.springframework.jdbc.datasource;
18
19 import java.lang.reflect.Method JavaDoc;
20 import java.sql.Connection JavaDoc;
21 import java.sql.SQLException JavaDoc;
22
23 import javax.sql.DataSource JavaDoc;
24
25 import org.apache.commons.logging.Log;
26 import org.apache.commons.logging.LogFactory;
27
28 import org.springframework.util.ReflectionUtils;
29 import org.springframework.util.StringUtils;
30
31 /**
32  * {@link DataSource} implementation that delegates all calls to a WebSphere
33  * target {@link DataSource}, typically obtained from JNDI, applying a current
34  * isolation level and/or current user credentials to every Connection obtained
35  * from it.
36  *
37  * <p>Uses IBM-specific API to get a JDBC Connection with a specific isolation
38  * level (and read-only flag) from a WebSphere DataSource
39  * (<a HREF="http://publib.boulder.ibm.com/infocenter/wasinfo/v5r1//topic/com.ibm.websphere.base.doc/info/aes/ae/rdat_extiapi.html">IBM code example</a>).
40  * Supports the transaction-specific isolation level exposed by
41  * {@link org.springframework.transaction.support.TransactionSynchronizationManager#getCurrentTransactionIsolationLevel()}.
42  * It's also possible to specify a default isolation level, to be applied when the
43  * current Spring-managed transaction does not define a specific isolation level.
44  *
45  * <p>Usage example, defining the target DataSource as an inner-bean JNDI lookup
46  * (of course, you can link to any WebSphere DataSource through a bean reference):
47  *
48  * <pre class="code">
49  * &lt;bean id="myDataSource" class="org.springframework.jdbc.datasource.WebSphereDataSourceAdapter"&gt;
50  * &lt;property name="targetDataSource"&gt;
51  * &lt;bean class="org.springframework.jndi.JndiObjectFactoryBean"&gt;
52  * &lt;property name="jndiName" value="jdbc/myds"/&gt;
53  * &lt;/bean&gt;
54  * &lt;/property&gt;
55  * &lt;/bean&gt;</pre>
56  *
57  * Thanks to Ricardo Olivieri for submitting the original implementation
58  * of this approach!
59  *
60  * @author Juergen Hoeller
61  * @author <a HREF="mailto:lari.hotari@sagire.fi">Lari Hotari</a>
62  * @author <a HREF="mailto:roliv@us.ibm.com">Ricardo N. Olivieri</a>
63  * @since 2.0.3
64  * @see com.ibm.websphere.rsadapter.JDBCConnectionSpec
65  * @see com.ibm.websphere.rsadapter.WSDataSource#getConnection(com.ibm.websphere.rsadapter.JDBCConnectionSpec)
66  * @see org.springframework.transaction.support.TransactionSynchronizationManager#getCurrentTransactionIsolationLevel()
67  * @see org.springframework.transaction.support.TransactionSynchronizationManager#isCurrentTransactionReadOnly()
68  */

69 public class WebSphereDataSourceAdapter extends IsolationLevelDataSourceAdapter {
70
71     protected final Log logger = LogFactory.getLog(getClass());
72
73     private Class JavaDoc wsDataSourceClass;
74
75     private Method JavaDoc newJdbcConnSpecMethod;
76
77     private Method JavaDoc wsDataSourceGetConnectionMethod;
78
79     private Method JavaDoc setTransactionIsolationMethod;
80
81     private Method JavaDoc setReadOnlyMethod;
82
83     private Method JavaDoc setUserNameMethod;
84
85     private Method JavaDoc setPasswordMethod;
86
87
88     /**
89      * This constructor retrieves the WebSphere JDBC connection spec API,
90      * so we can get obtain specific WebSphere Connections using reflection.
91      */

92     public WebSphereDataSourceAdapter() {
93         try {
94             this.wsDataSourceClass = getClass().getClassLoader().loadClass("com.ibm.websphere.rsadapter.WSDataSource");
95             Class JavaDoc jdbcConnSpecClass = getClass().getClassLoader().loadClass("com.ibm.websphere.rsadapter.JDBCConnectionSpec");
96             Class JavaDoc wsrraFactoryClass = getClass().getClassLoader().loadClass("com.ibm.websphere.rsadapter.WSRRAFactory");
97             this.newJdbcConnSpecMethod = wsrraFactoryClass.getMethod("createJDBCConnectionSpec", null);
98             this.wsDataSourceGetConnectionMethod =
99                     this.wsDataSourceClass.getMethod("getConnection", new Class JavaDoc[] {jdbcConnSpecClass});
100             this.setTransactionIsolationMethod =
101                     jdbcConnSpecClass.getMethod("setTransactionIsolation", new Class JavaDoc[] {int.class});
102             this.setReadOnlyMethod = jdbcConnSpecClass.getMethod("setReadOnly", new Class JavaDoc[] {Boolean JavaDoc.class});
103             this.setUserNameMethod = jdbcConnSpecClass.getMethod("setUserName", new Class JavaDoc[] {String JavaDoc.class});
104             this.setPasswordMethod = jdbcConnSpecClass.getMethod("setPassword", new Class JavaDoc[] {String JavaDoc.class});
105         }
106         catch (Exception JavaDoc ex) {
107             throw new IllegalStateException JavaDoc(
108                     "Could not initialize WebSphereDataSourceAdapter because WebSphere API classes are not available: " + ex);
109         }
110     }
111
112     /**
113      * Checks that the specified 'targetDataSource' actually is
114      * a WebSphere WSDataSource.
115      */

116     public void afterPropertiesSet() {
117         super.afterPropertiesSet();
118
119         if (!this.wsDataSourceClass.isInstance(getTargetDataSource())) {
120             throw new IllegalStateException JavaDoc(
121                     "Specified 'targetDataSource' is not a WebSphere WSDataSource: " + getTargetDataSource());
122         }
123     }
124
125
126     /**
127      * Builds a WebSphere JDBCConnectionSpec object for the current settings
128      * and calls <code>WSDataSource.getConnection(JDBCConnectionSpec)</code>.
129      * @see #createConnectionSpec
130      * @see com.ibm.websphere.rsadapter.WSDataSource#getConnection(com.ibm.websphere.rsadapter.JDBCConnectionSpec)
131      */

132     protected Connection JavaDoc doGetConnection(String JavaDoc username, String JavaDoc password) throws SQLException JavaDoc {
133         // Create JDBCConnectionSpec using current isolation level value and read-only flag.
134
Object JavaDoc connSpec = createConnectionSpec(
135                 getCurrentIsolationLevel(), getCurrentReadOnlyFlag(), username, password);
136         if (logger.isDebugEnabled()) {
137             logger.debug("Obtaining JDBC Connection from WebSphere DataSource [" +
138                     getTargetDataSource() + "], using ConnectionSpec [" + connSpec + "]");
139         }
140         // Create Connection through invoking WSDataSource.getConnection(JDBCConnectionSpec)
141
return (Connection JavaDoc) ReflectionUtils.invokeMethod(
142                 this.wsDataSourceGetConnectionMethod, getTargetDataSource(), new Object JavaDoc[] {connSpec});
143     }
144
145     /**
146      * Create a WebSphere <code>JDBCConnectionSpec</code> object for the given charateristics.
147      * <p>The default implementation uses reflection to apply the given settings.
148      * Can be overridden in subclasses to customize the JDBCConnectionSpec object
149      * (<a HREF="http://publib.boulder.ibm.com/infocenter/wasinfo/v6r0/topic/com.ibm.websphere.javadoc.doc/public_html/api/com/ibm/websphere/rsadapter/JDBCConnectionSpec.html">JDBCConnectionSpec javadoc</a>;
150      * <a HREF="http://www.ibm.com/developerworks/websphere/library/techarticles/0404_tang/0404_tang.html">IBM developerWorks article</a>).
151      * @param isolationLevel the isolation level to apply (or <code>null</code> if none)
152      * @param readOnlyFlag the read-only flag to apply (or <code>null</code> if none)
153      * @param username the username to apply (<code>null</code> or empty indicates the default)
154      * @param password the password to apply (may be <code>null</code> or empty)
155      * @throws SQLException if thrown by JDBCConnectionSpec API methods
156      * @see com.ibm.websphere.rsadapter.JDBCConnectionSpec
157      */

158     protected Object JavaDoc createConnectionSpec(
159             Integer JavaDoc isolationLevel, Boolean JavaDoc readOnlyFlag, String JavaDoc username, String JavaDoc password) throws SQLException JavaDoc {
160
161         Object JavaDoc connSpec = ReflectionUtils.invokeMethod(this.newJdbcConnSpecMethod, null);
162         if (isolationLevel != null) {
163             ReflectionUtils.invokeMethod(this.setTransactionIsolationMethod, connSpec, new Object JavaDoc[] {isolationLevel});
164         }
165         if (readOnlyFlag != null) {
166             ReflectionUtils.invokeMethod(this.setReadOnlyMethod, connSpec, new Object JavaDoc[] {readOnlyFlag});
167         }
168         // If the username is empty, we'll simply let the target DataSource
169
// use its default credentials.
170
if (StringUtils.hasLength(username)) {
171             ReflectionUtils.invokeMethod(this.setUserNameMethod, connSpec, new Object JavaDoc[] {username});
172             ReflectionUtils.invokeMethod(this.setPasswordMethod, connSpec, new Object JavaDoc[] {password});
173         }
174         return connSpec;
175     }
176
177 }
178
Popular Tags