KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > jca > cci > connection > ConnectionFactoryUtils


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.jca.cci.connection;
18
19 import javax.resource.ResourceException JavaDoc;
20 import javax.resource.cci.Connection JavaDoc;
21 import javax.resource.cci.ConnectionFactory JavaDoc;
22 import javax.resource.cci.ConnectionSpec JavaDoc;
23
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26
27 import org.springframework.jca.cci.CannotGetCciConnectionException;
28 import org.springframework.transaction.support.TransactionSynchronizationAdapter;
29 import org.springframework.transaction.support.TransactionSynchronizationManager;
30 import org.springframework.util.Assert;
31  
32 /**
33  * Helper class that provides static methods for obtaining CCI Connections
34  * from a {@link javax.resource.cci.ConnectionFactory}. Includes special
35  * support for Spring-managed transactional Connections, e.g. managed
36  * by {@link CciLocalTransactionManager} or
37  * {@link org.springframework.transaction.jta.JtaTransactionManager}.
38  *
39  * <p>Used internally by {@link org.springframework.jca.cci.core.CciTemplate},
40  * Spring's CCI operation objects and the {@link CciLocalTransactionManager}.
41  * Can also be used directly in application code.
42  *
43  * @author Thierry Templier
44  * @author Juergen Hoeller
45  * @since 1.2
46  * @see #getConnection
47  * @see #releaseConnection
48  * @see CciLocalTransactionManager
49  * @see org.springframework.transaction.jta.JtaTransactionManager
50  * @see org.springframework.transaction.support.TransactionSynchronizationManager
51  */

52 public abstract class ConnectionFactoryUtils {
53
54     private static final Log logger = LogFactory.getLog(ConnectionFactoryUtils.class);
55
56
57     /**
58      * Obtain a Connection from the given ConnectionFactory. Translates ResourceExceptions
59      * into the Spring hierarchy of unchecked generic data access exceptions, simplifying
60      * calling code and making any exception that is thrown more meaningful.
61      * <p>Is aware of a corresponding Connection bound to the current thread, for example
62      * when using {@link CciLocalTransactionManager}. Will bind a Connection to the thread
63      * if transaction synchronization is active (e.g. if in a JTA transaction).
64      * @param cf the ConnectionFactory to obtain Connection from
65      * @return a CCI Connection from the given ConnectionFactory
66      * @throws org.springframework.jca.cci.CannotGetCciConnectionException
67      * if the attempt to get a Connection failed
68      * @see #releaseConnection
69      */

70     public static Connection JavaDoc getConnection(ConnectionFactory JavaDoc cf) throws CannotGetCciConnectionException {
71         return getConnection(cf, null);
72     }
73
74     /**
75      * Obtain a Connection from the given ConnectionFactory. Translates ResourceExceptions
76      * into the Spring hierarchy of unchecked generic data access exceptions, simplifying
77      * calling code and making any exception that is thrown more meaningful.
78      * <p>Is aware of a corresponding Connection bound to the current thread, for example
79      * when using {@link CciLocalTransactionManager}. Will bind a Connection to the thread
80      * if transaction synchronization is active (e.g. if in a JTA transaction).
81      * @param cf the ConnectionFactory to obtain Connection from
82      * @param spec the ConnectionSpec for the desired Connection (may be <code>null</code>).
83      * Note: If this is specified, a new Connection will be obtained for every call,
84      * without participating in a shared transactional Connection.
85      * @return a CCI Connection from the given ConnectionFactory
86      * @throws org.springframework.jca.cci.CannotGetCciConnectionException
87      * if the attempt to get a Connection failed
88      * @see #releaseConnection
89      */

90     public static Connection JavaDoc getConnection(ConnectionFactory JavaDoc cf, ConnectionSpec JavaDoc spec)
91             throws CannotGetCciConnectionException {
92         try {
93             if (spec != null) {
94                 Assert.notNull(cf, "No ConnectionFactory specified");
95                 return cf.getConnection(spec);
96             }
97             else {
98                 return doGetConnection(cf);
99             }
100         }
101         catch (ResourceException JavaDoc ex) {
102             throw new CannotGetCciConnectionException("Could not get CCI Connection", ex);
103         }
104     }
105
106     /**
107      * Actually obtain a CCI Connection from the given ConnectionFactory.
108      * Same as {@link #getConnection}, but throwing the original ResourceException.
109      * <p>Is aware of a corresponding Connection bound to the current thread, for example
110      * when using {@link CciLocalTransactionManager}. Will bind a Connection to the thread
111      * if transaction synchronization is active (e.g. if in a JTA transaction).
112      * <p>Directly accessed by {@link TransactionAwareConnectionFactoryProxy}.
113      * @param cf the ConnectionFactory to obtain Connection from
114      * @return a CCI Connection from the given ConnectionFactory
115      * @throws ResourceException if thrown by CCI API methods
116      * @see #doReleaseConnection
117      */

118     public static Connection JavaDoc doGetConnection(ConnectionFactory JavaDoc cf) throws ResourceException JavaDoc {
119         Assert.notNull(cf, "No ConnectionFactory specified");
120
121         ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(cf);
122         if (conHolder != null) {
123             return conHolder.getConnection();
124         }
125
126         logger.debug("Opening CCI Connection");
127         Connection JavaDoc con = cf.getConnection();
128
129         if (TransactionSynchronizationManager.isSynchronizationActive()) {
130             logger.debug("Registering transaction synchronization for CCI Connection");
131             conHolder = new ConnectionHolder(con);
132             conHolder.setSynchronizedWithTransaction(true);
133             TransactionSynchronizationManager.registerSynchronization(new ConnectionSynchronization(conHolder, cf));
134             TransactionSynchronizationManager.bindResource(cf, conHolder);
135         }
136
137         return con;
138     }
139
140     /**
141      * Determine whether the given JCA CCI Connection is transactional, that is,
142      * bound to the current thread by Spring's transaction facilities.
143      * @param con the Connection to check
144      * @param cf the ConnectionFactory that the Connection was obtained from
145      * (may be <code>null</code>)
146      * @return whether the Connection is transactional
147      */

148     public static boolean isConnectionTransactional(Connection JavaDoc con, ConnectionFactory JavaDoc cf) {
149         if (cf == null) {
150             return false;
151         }
152         ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(cf);
153         return (conHolder != null && conHolder.getConnection() == con);
154     }
155
156     /**
157      * Close the given Connection, obtained from the given ConnectionFactory,
158      * if it is not managed externally (that is, not bound to the thread).
159      * @param con the Connection to close if necessary
160      * (if this is <code>null</code>, the call will be ignored)
161      * @param cf the ConnectionFactory that the Connection was obtained from
162      * (can be <code>null</code>)
163      * @see #getConnection
164      */

165     public static void releaseConnection(Connection JavaDoc con, ConnectionFactory JavaDoc cf) {
166         try {
167             doReleaseConnection(con, cf);
168         }
169         catch (ResourceException JavaDoc ex) {
170             logger.debug("Could not close CCI Connection", ex);
171         }
172         catch (Throwable JavaDoc ex) {
173             // We don't trust the CCI driver: It might throw RuntimeException or Error.
174
logger.debug("Unexpected exception on closing CCI Connection", ex);
175         }
176     }
177
178     /**
179      * Actually close the given Connection, obtained from the given ConnectionFactory.
180      * Same as {@link #releaseConnection}, but throwing the original ResourceException.
181      * <p>Directly accessed by {@link TransactionAwareConnectionFactoryProxy}.
182      * @param con the Connection to close if necessary
183      * (if this is <code>null</code>, the call will be ignored)
184      * @param cf the ConnectionFactory that the Connection was obtained from
185      * (can be <code>null</code>)
186      * @throws ResourceException if thrown by JCA CCI methods
187      * @see #doGetConnection
188      */

189     public static void doReleaseConnection(Connection JavaDoc con, ConnectionFactory JavaDoc cf) throws ResourceException JavaDoc {
190         if (con == null || isConnectionTransactional(con, cf)) {
191             return;
192         }
193         con.close();
194     }
195
196
197     /**
198      * Callback for resource cleanup at the end of a non-native CCI transaction
199      * (e.g. when participating in a JTA transaction).
200      */

201     private static class ConnectionSynchronization extends TransactionSynchronizationAdapter {
202
203         private final ConnectionHolder connectionHolder;
204
205         private final ConnectionFactory JavaDoc connectionFactory;
206
207         private boolean holderActive = true;
208
209         public ConnectionSynchronization(ConnectionHolder connectionHolder, ConnectionFactory JavaDoc connectionFactory) {
210             this.connectionHolder = connectionHolder;
211             this.connectionFactory = connectionFactory;
212         }
213
214         public void suspend() {
215             if (this.holderActive) {
216                 TransactionSynchronizationManager.unbindResource(this.connectionFactory);
217             }
218         }
219
220         public void resume() {
221             if (this.holderActive) {
222                 TransactionSynchronizationManager.bindResource(this.connectionFactory, this.connectionHolder);
223             }
224         }
225
226         public void beforeCompletion() {
227             TransactionSynchronizationManager.unbindResource(this.connectionFactory);
228             this.holderActive = false;
229             releaseConnection(this.connectionHolder.getConnection(), this.connectionFactory);
230         }
231     }
232
233 }
234
Popular Tags