KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > orm > jdo > PersistenceManagerFactoryUtils


1 /*
2  * Copyright 2002-2006 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.orm.jdo;
18
19 import javax.jdo.JDODataStoreException;
20 import javax.jdo.JDOException;
21 import javax.jdo.JDOFatalDataStoreException;
22 import javax.jdo.JDOFatalUserException;
23 import javax.jdo.JDOObjectNotFoundException;
24 import javax.jdo.JDOOptimisticVerificationException;
25 import javax.jdo.JDOUserException;
26 import javax.jdo.PersistenceManager;
27 import javax.jdo.PersistenceManagerFactory;
28 import javax.jdo.Query;
29 import javax.sql.DataSource JavaDoc;
30
31 import org.apache.commons.logging.Log;
32 import org.apache.commons.logging.LogFactory;
33
34 import org.springframework.dao.DataAccessException;
35 import org.springframework.dao.DataAccessResourceFailureException;
36 import org.springframework.jdbc.datasource.DataSourceUtils;
37 import org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator;
38 import org.springframework.jdbc.support.SQLExceptionTranslator;
39 import org.springframework.jdbc.support.SQLStateSQLExceptionTranslator;
40 import org.springframework.transaction.support.TransactionSynchronizationAdapter;
41 import org.springframework.transaction.support.TransactionSynchronizationManager;
42 import org.springframework.util.Assert;
43
44 /**
45  * Helper class featuring methods for JDO PersistenceManager handling,
46  * allowing for reuse of PersistenceManager instances within transactions.
47  * Also provides support for exception translation.
48  *
49  * <p>Used by JdoTemplate, JdoInterceptor, and JdoTransactionManager.
50  * Can also be used directly in application code, e.g. in combination
51  * with JdoInterceptor.
52  *
53  * @author Juergen Hoeller
54  * @since 03.06.2003
55  * @see JdoTemplate
56  * @see JdoInterceptor
57  * @see JdoTransactionManager
58  */

59 public abstract class PersistenceManagerFactoryUtils {
60
61     /**
62      * Order value for TransactionSynchronization objects that clean up JDO
63      * PersistenceManagers. Return DataSourceUtils.CONNECTION_SYNCHRONIZATION_ORDER - 100
64      * to execute PersistenceManager cleanup before JDBC Connection cleanup, if any.
65      * @see org.springframework.jdbc.datasource.DataSourceUtils#CONNECTION_SYNCHRONIZATION_ORDER
66      */

67     public static final int PERSISTENCE_MANAGER_SYNCHRONIZATION_ORDER =
68             DataSourceUtils.CONNECTION_SYNCHRONIZATION_ORDER - 100;
69
70     private static final Log logger = LogFactory.getLog(PersistenceManagerFactoryUtils.class);
71
72
73     /**
74      * Create an appropriate SQLExceptionTranslator for the given PersistenceManagerFactory.
75      * <p>If a DataSource is found, creates a SQLErrorCodeSQLExceptionTranslator for the
76      * DataSource; else, falls back to a SQLStateSQLExceptionTranslator.
77      * @param connectionFactory the connection factory of the PersistenceManagerFactory
78      * (may be <code>null</code>)
79      * @return the SQLExceptionTranslator (never <code>null</code>)
80      * @see javax.jdo.PersistenceManagerFactory#getConnectionFactory()
81      * @see org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator
82      * @see org.springframework.jdbc.support.SQLStateSQLExceptionTranslator
83      */

84     static SQLExceptionTranslator newJdbcExceptionTranslator(Object JavaDoc connectionFactory) {
85         // Check for PersistenceManagerFactory's DataSource.
86
if (connectionFactory instanceof DataSource JavaDoc) {
87             return new SQLErrorCodeSQLExceptionTranslator((DataSource JavaDoc) connectionFactory);
88         }
89         else {
90             return new SQLStateSQLExceptionTranslator();
91         }
92     }
93
94     /**
95      * Obtain a JDO PersistenceManager via the given factory. Is aware of a
96      * corresponding PersistenceManager bound to the current thread,
97      * for example when using JdoTransactionManager. Will create a new
98      * PersistenceManager else, if "allowCreate" is <code>true</code>.
99      * @param pmf PersistenceManagerFactory to create the PersistenceManager with
100      * @param allowCreate if a non-transactional PersistenceManager should be created
101      * when no transactional PersistenceManager can be found for the current thread
102      * @return the PersistenceManager
103      * @throws DataAccessResourceFailureException if the PersistenceManager couldn't be obtained
104      * @throws IllegalStateException if no thread-bound PersistenceManager found and
105      * "allowCreate" is <code>false</code>
106      * @see JdoTransactionManager
107      */

108     public static PersistenceManager getPersistenceManager(PersistenceManagerFactory pmf, boolean allowCreate)
109         throws DataAccessResourceFailureException, IllegalStateException JavaDoc {
110
111         try {
112             return doGetPersistenceManager(pmf, allowCreate);
113         }
114         catch (JDOException ex) {
115             throw new DataAccessResourceFailureException("Could not obtain JDO PersistenceManager", ex);
116         }
117     }
118
119     /**
120      * Obtain a JDO PersistenceManager via the given factory. Is aware of a
121      * corresponding PersistenceManager bound to the current thread,
122      * for example when using JdoTransactionManager. Will create a new
123      * PersistenceManager else, if "allowCreate" is <code>true</code>.
124      * <p>Same as <code>getPersistenceManager</code>, but throwing the original JDOException.
125      * @param pmf PersistenceManagerFactory to create the PersistenceManager with
126      * @param allowCreate if a non-transactional PersistenceManager should be created
127      * when no transactional PersistenceManager can be found for the current thread
128      * @return the PersistenceManager
129      * @throws JDOException if the PersistenceManager couldn't be created
130      * @throws IllegalStateException if no thread-bound PersistenceManager found and
131      * "allowCreate" is <code>false</code>
132      * @see #getPersistenceManager(javax.jdo.PersistenceManagerFactory, boolean)
133      * @see JdoTransactionManager
134      */

135     public static PersistenceManager doGetPersistenceManager(PersistenceManagerFactory pmf, boolean allowCreate)
136         throws JDOException, IllegalStateException JavaDoc {
137
138         Assert.notNull(pmf, "No PersistenceManagerFactory specified");
139
140         PersistenceManagerHolder pmHolder =
141                 (PersistenceManagerHolder) TransactionSynchronizationManager.getResource(pmf);
142         if (pmHolder != null) {
143             if (!pmHolder.isSynchronizedWithTransaction() &&
144                     TransactionSynchronizationManager.isSynchronizationActive()) {
145                 pmHolder.setSynchronizedWithTransaction(true);
146                 TransactionSynchronizationManager.registerSynchronization(
147                         new PersistenceManagerSynchronization(pmHolder, pmf, false));
148             }
149             return pmHolder.getPersistenceManager();
150         }
151
152         if (!allowCreate && !TransactionSynchronizationManager.isSynchronizationActive()) {
153             throw new IllegalStateException JavaDoc("No JDO PersistenceManager bound to thread, " +
154                     "and configuration does not allow creation of non-transactional one here");
155         }
156
157         logger.debug("Opening JDO PersistenceManager");
158         PersistenceManager pm = pmf.getPersistenceManager();
159
160         if (TransactionSynchronizationManager.isSynchronizationActive()) {
161             logger.debug("Registering transaction synchronization for JDO PersistenceManager");
162             // Use same PersistenceManager for further JDO actions within the transaction.
163
// Thread object will get removed by synchronization at transaction completion.
164
pmHolder = new PersistenceManagerHolder(pm);
165             pmHolder.setSynchronizedWithTransaction(true);
166             TransactionSynchronizationManager.registerSynchronization(
167                     new PersistenceManagerSynchronization(pmHolder, pmf, true));
168             TransactionSynchronizationManager.bindResource(pmf, pmHolder);
169         }
170
171         return pm;
172     }
173
174     /**
175      * Return whether the given JDO PersistenceManager is transactional, that is,
176      * bound to the current thread by Spring's transaction facilities.
177      * @param pm the JDO PersistenceManager to check
178      * @param pmf JDO PersistenceManagerFactory that the PersistenceManager
179      * was created with (can be <code>null</code>)
180      * @return whether the PersistenceManager is transactional
181      */

182     public static boolean isPersistenceManagerTransactional(
183             PersistenceManager pm, PersistenceManagerFactory pmf) {
184
185         if (pmf == null) {
186             return false;
187         }
188         PersistenceManagerHolder pmHolder =
189                 (PersistenceManagerHolder) TransactionSynchronizationManager.getResource(pmf);
190         return (pmHolder != null && pm == pmHolder.getPersistenceManager());
191     }
192
193     /**
194      * Apply the current transaction timeout, if any, to the given JDO Query object.
195      * @param query the JDO Query object
196      * @param pmf JDO PersistenceManagerFactory that the Query was created for
197      * @param jdoDialect the JdoDialect to use for applying a query timeout
198      * (must not be <code>null</code>)
199      * @see JdoDialect#applyQueryTimeout
200      */

201     public static void applyTransactionTimeout(
202             Query query, PersistenceManagerFactory pmf, JdoDialect jdoDialect) throws JDOException {
203
204         Assert.notNull(query, "No Query object specified");
205         PersistenceManagerHolder pmHolder =
206             (PersistenceManagerHolder) TransactionSynchronizationManager.getResource(pmf);
207         if (pmHolder != null && pmHolder.hasTimeout()) {
208             jdoDialect.applyQueryTimeout(query, pmHolder.getTimeToLiveInSeconds());
209         }
210     }
211
212     /**
213      * Convert the given JDOException to an appropriate exception from the
214      * <code>org.springframework.dao</code> hierarchy.
215      * <p>The most important cases like object not found or optimistic locking
216      * failure are covered here. For more fine-granular conversion, JdoAccessor and
217      * JdoTransactionManager support sophisticated translation of exceptions via a
218      * JdoDialect.
219      * @param ex JDOException that occured
220      * @return the corresponding DataAccessException instance
221      * @see JdoAccessor#convertJdoAccessException
222      * @see JdoTransactionManager#convertJdoAccessException
223      * @see JdoDialect#translateException
224      */

225     public static DataAccessException convertJdoAccessException(JDOException ex) {
226         if (ex instanceof JDOObjectNotFoundException) {
227             throw new JdoObjectRetrievalFailureException((JDOObjectNotFoundException) ex);
228         }
229         if (ex instanceof JDOOptimisticVerificationException) {
230             throw new JdoOptimisticLockingFailureException((JDOOptimisticVerificationException) ex);
231         }
232         if (ex instanceof JDODataStoreException) {
233             return new JdoResourceFailureException((JDODataStoreException) ex);
234         }
235         if (ex instanceof JDOFatalDataStoreException) {
236             return new JdoResourceFailureException((JDOFatalDataStoreException) ex);
237         }
238         if (ex instanceof JDOUserException) {
239             return new JdoUsageException((JDOUserException) ex);
240         }
241         if (ex instanceof JDOFatalUserException) {
242             return new JdoUsageException((JDOFatalUserException) ex);
243         }
244         // fallback
245
return new JdoSystemException(ex);
246     }
247
248     /**
249      * Close the given PersistenceManager, created via the given factory,
250      * if it is not managed externally (i.e. not bound to the thread).
251      * @param pm PersistenceManager to close
252      * @param pmf PersistenceManagerFactory that the PersistenceManager was created with
253      * (can be <code>null</code>)
254      */

255     public static void releasePersistenceManager(PersistenceManager pm, PersistenceManagerFactory pmf) {
256         try {
257             doReleasePersistenceManager(pm, pmf);
258         }
259         catch (JDOException ex) {
260             logger.debug("Could not close JDO PersistenceManager", ex);
261         }
262         catch (Throwable JavaDoc ex) {
263             logger.debug("Unexpected exception on closing JDO PersistenceManager", ex);
264         }
265     }
266
267     /**
268      * Actually release a PersistenceManager for the given factory.
269      * Same as <code>releasePersistenceManager</code>, but throwing the original JDOException.
270      * @param pm PersistenceManager to close
271      * @param pmf PersistenceManagerFactory that the PersistenceManager was created with
272      * (can be <code>null</code>)
273      * @throws JDOException if thrown by JDO methods
274      */

275     public static void doReleasePersistenceManager(PersistenceManager pm, PersistenceManagerFactory pmf)
276             throws JDOException {
277
278         if (pm == null) {
279             return;
280         }
281         // Only release non-transactional PersistenceManagers.
282
if (!isPersistenceManagerTransactional(pm, pmf)) {
283             logger.debug("Closing JDO PersistenceManager");
284             pm.close();
285         }
286     }
287
288
289     /**
290      * Callback for resource cleanup at the end of a non-JDO transaction
291      * (e.g. when participating in a JtaTransactionManager transaction).
292      * @see org.springframework.transaction.jta.JtaTransactionManager
293      */

294     private static class PersistenceManagerSynchronization extends TransactionSynchronizationAdapter {
295
296         private final PersistenceManagerHolder persistenceManagerHolder;
297
298         private final PersistenceManagerFactory persistenceManagerFactory;
299
300         private final boolean newPersistenceManager;
301
302         private boolean holderActive = true;
303
304         public PersistenceManagerSynchronization(
305                 PersistenceManagerHolder pmHolder, PersistenceManagerFactory pmf, boolean newPersistenceManager) {
306             this.persistenceManagerHolder = pmHolder;
307             this.persistenceManagerFactory = pmf;
308             this.newPersistenceManager = newPersistenceManager;
309         }
310
311         public int getOrder() {
312             return PERSISTENCE_MANAGER_SYNCHRONIZATION_ORDER;
313         }
314
315         public void suspend() {
316             if (this.holderActive) {
317                 TransactionSynchronizationManager.unbindResource(this.persistenceManagerFactory);
318             }
319         }
320
321         public void resume() {
322             if (this.holderActive) {
323                 TransactionSynchronizationManager.bindResource(
324                         this.persistenceManagerFactory, this.persistenceManagerHolder);
325             }
326         }
327
328         public void beforeCompletion() {
329             if (this.newPersistenceManager) {
330                 TransactionSynchronizationManager.unbindResource(this.persistenceManagerFactory);
331                 this.holderActive = false;
332                 releasePersistenceManager(
333                         this.persistenceManagerHolder.getPersistenceManager(), this.persistenceManagerFactory);
334             }
335         }
336
337         public void afterCompletion(int status) {
338             this.persistenceManagerHolder.setSynchronizedWithTransaction(false);
339         }
340     }
341
342 }
343
Popular Tags