001: /*
002: * Copyright 2002-2007 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.jca.cci.connection;
018:
019: import javax.resource.ResourceException;
020: import javax.resource.cci.Connection;
021: import javax.resource.cci.ConnectionSpec;
022:
023: /**
024: * An adapter for a target CCI {@link javax.resource.cci.ConnectionFactory},
025: * applying the given ConnectionSpec to every standard <code>getConnection()</code>
026: * call, that is, implicitly invoking <code>getConnection(ConnectionSpec)</code>
027: * on the target. All other methods simply delegate to the corresponding methods
028: * of the target ConnectionFactory.
029: *
030: * <p>Can be used to proxy a target JNDI ConnectionFactory that does not have a
031: * ConnectionSpec configured. Client code can work with the ConnectionFactory
032: * without passing in a ConnectionSpec on every <code>getConnection()</code> call.
033: *
034: * <p>In the following example, client code can simply transparently work with
035: * the preconfigured "myConnectionFactory", implicitly accessing
036: * "myTargetConnectionFactory" with the specified user credentials.
037: *
038: * <pre class="code">
039: * <bean id="myTargetConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
040: * <property name="jndiName" value="java:comp/env/cci/mycf"/>
041: * </bean>
042: *
043: * <bean id="myConnectionFactory" class="org.springframework.jca.cci.connection.ConnectionSpecConnectionFactoryAdapter">
044: * <property name="targetConnectionFactory" ref="myTargetConnectionFactory"/>
045: * <property name="connectionSpec">
046: * <bean class="your.resource.adapter.ConnectionSpecImpl">
047: * <property name="username" value="myusername"/>
048: * <property name="password" value="mypassword"/>
049: * </bean>
050: * </property>
051: * </bean></pre>
052: *
053: * <p>If the "connectionSpec" is empty, this proxy will simply delegate to the
054: * standard <code>getConnection()</code> method of the target ConnectionFactory.
055: * This can be used to keep a UserCredentialsConnectionFactoryAdapter bean definition
056: * just for the <i>option</i> of implicitly passing in a ConnectionSpec if the
057: * particular target ConnectionFactory requires it.
058: *
059: * @author Juergen Hoeller
060: * @since 1.2
061: * @see #getConnection
062: */
063: public class ConnectionSpecConnectionFactoryAdapter extends
064: DelegatingConnectionFactory {
065:
066: private ConnectionSpec connectionSpec;
067:
068: private final ThreadLocal threadBoundSpec = new ThreadLocal();
069:
070: /**
071: * Set the ConnectionSpec that this adapter should use for retrieving Connections.
072: * Default is none.
073: */
074: public void setConnectionSpec(ConnectionSpec connectionSpec) {
075: this .connectionSpec = connectionSpec;
076: }
077:
078: /**
079: * Set a ConnectionSpec for this proxy and the current thread.
080: * The given ConnectionSpec will be applied to all subsequent
081: * <code>getConnection()</code> calls on this ConnectionFactory proxy.
082: * <p>This will override any statically specified "connectionSpec" property.
083: * @param spec the ConnectionSpec to apply
084: * @see #removeConnectionSpecFromCurrentThread
085: */
086: public void setConnectionSpecForCurrentThread(ConnectionSpec spec) {
087: this .threadBoundSpec.set(spec);
088: }
089:
090: /**
091: * Remove any ConnectionSpec for this proxy from the current thread.
092: * A statically specified ConnectionSpec applies again afterwards.
093: * @see #setConnectionSpecForCurrentThread
094: */
095: public void removeConnectionSpecFromCurrentThread() {
096: this .threadBoundSpec.set(null);
097: }
098:
099: /**
100: * Determine whether there is currently a thread-bound ConnectionSpec,
101: * using it if available, falling back to the statically specified
102: * "connectionSpec" property else.
103: * @see #doGetConnection
104: */
105: public final Connection getConnection() throws ResourceException {
106: ConnectionSpec threadSpec = (ConnectionSpec) this .threadBoundSpec
107: .get();
108: if (threadSpec != null) {
109: return doGetConnection(threadSpec);
110: } else {
111: return doGetConnection(this .connectionSpec);
112: }
113: }
114:
115: /**
116: * This implementation delegates to the <code>getConnection(ConnectionSpec)</code>
117: * method of the target ConnectionFactory, passing in the specified user credentials.
118: * If the specified username is empty, it will simply delegate to the standard
119: * <code>getConnection()</code> method of the target ConnectionFactory.
120: * @param spec the ConnectionSpec to apply
121: * @return the Connection
122: * @see javax.resource.cci.ConnectionFactory#getConnection(javax.resource.cci.ConnectionSpec)
123: * @see javax.resource.cci.ConnectionFactory#getConnection()
124: */
125: protected Connection doGetConnection(ConnectionSpec spec)
126: throws ResourceException {
127: if (getTargetConnectionFactory() == null) {
128: throw new IllegalStateException(
129: "targetConnectionFactory is required");
130: }
131: if (spec != null) {
132: return getTargetConnectionFactory().getConnection(spec);
133: } else {
134: return getTargetConnectionFactory().getConnection();
135: }
136: }
137:
138: }
|