/tests/com/google/appengine/datanucleus/jpa/JPATestCase.java

http://datanucleus-appengine.googlecode.com/ · Java · 227 lines · 167 code · 31 blank · 29 comment · 18 complexity · 9e2be125e74fd993094c24caa7f0a831 MD5 · raw file

  1. /*********************b*************************************************
  2. Copyright (c) 2009 Google Inc.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. **********************************************************************/
  13. package com.google.appengine.datanucleus.jpa;
  14. import com.google.appengine.api.datastore.*;
  15. import com.google.appengine.datanucleus.DatastoreManager;
  16. import com.google.appengine.datanucleus.DatastoreTestCase;
  17. import com.google.appengine.datanucleus.EntityUtils;
  18. import com.google.appengine.datanucleus.StorageVersion;
  19. import org.datanucleus.ClassLoaderResolver;
  20. import org.datanucleus.NucleusContext;
  21. import org.datanucleus.api.jpa.JPAEntityManager;
  22. import org.datanucleus.api.jpa.JPAEntityManagerFactory;
  23. import org.datanucleus.metadata.MetaDataManager;
  24. import org.datanucleus.ExecutionContext;
  25. import org.datanucleus.store.mapped.MappedStoreManager;
  26. import java.util.List;
  27. import java.util.Map;
  28. import java.util.concurrent.ConcurrentHashMap;
  29. import javax.persistence.EntityManager;
  30. import javax.persistence.EntityManagerFactory;
  31. import javax.persistence.Persistence;
  32. /**
  33. * @author Max Ross <maxr@google.com>
  34. */
  35. public class JPATestCase extends DatastoreTestCase {
  36. private static
  37. ThreadLocal<Map<EntityManagerFactoryName, EntityManagerFactory>> emfCache =
  38. new ThreadLocal<Map<EntityManagerFactoryName, EntityManagerFactory>>() {
  39. @Override
  40. protected Map<EntityManagerFactoryName, EntityManagerFactory> initialValue() {
  41. // this shouldn't be necessary but I get concurrent mod exceptions
  42. return new ConcurrentHashMap<EntityManagerFactoryName, EntityManagerFactory>();
  43. }
  44. };
  45. protected EntityManagerFactory emf;
  46. protected EntityManager em;
  47. protected DatastoreService ds;
  48. @Override
  49. protected void setUp() throws Exception {
  50. super.setUp();
  51. ds = DatastoreServiceFactory.getDatastoreService();
  52. emf = emfCache.get().get(getEntityManagerFactoryName());
  53. if (emf == null || !emf.isOpen()) {
  54. emf = Persistence.createEntityManagerFactory(getEntityManagerFactoryName().name());
  55. if (cacheManagers()) {
  56. emfCache.get().put(getEntityManagerFactoryName(), emf);
  57. }
  58. }
  59. em = emf.createEntityManager();
  60. }
  61. public enum EntityManagerFactoryName {
  62. // nonTransactionalRead and nonTransactionalWrite are true
  63. transactional_ds_non_transactional_ops_allowed,
  64. // nonTransactionalRead and nonTransactionalWrite are false
  65. transactional_ds_non_transactional_ops_not_allowed,
  66. // nonTransactionalRead and nonTransactionalWrite are true
  67. nontransactional_ds_non_transactional_ops_allowed,
  68. // nonTransactionalRead and nonTransactionalWrite are false
  69. nontransactional_ds_non_transactional_ops_not_allowed,
  70. originalStorageVersion,
  71. }
  72. /**
  73. * By default we use a datasource that requires txns.
  74. * Override this if your test needs to use a different instance.
  75. */
  76. protected EntityManagerFactoryName getEntityManagerFactoryName() {
  77. return EntityManagerFactoryName.transactional_ds_non_transactional_ops_not_allowed;
  78. }
  79. @Override
  80. protected void tearDown() throws Exception {
  81. try {
  82. if (em.isOpen()) {
  83. if (em.getTransaction().isActive()) {
  84. em.getTransaction().rollback();
  85. }
  86. em.close();
  87. }
  88. em = null;
  89. // see if anybody closed any of our emfs and if so just remove them from the cache -
  90. // we'll rebuild it the next time it's needed.
  91. for (Map.Entry<EntityManagerFactoryName, EntityManagerFactory> entry : emfCache.get().entrySet()) {
  92. if (!entry.getValue().isOpen()) {
  93. emfCache.get().remove(entry.getKey());
  94. }
  95. }
  96. if (!cacheManagers() && emf.isOpen()) {
  97. emf.close();
  98. }
  99. emf = null;
  100. } finally {
  101. super.tearDown();
  102. }
  103. }
  104. protected DatastoreManager getDatastoreManagerForEM(EntityManager em) {
  105. return (DatastoreManager) ((JPAEntityManager)em).getExecutionContext().getStoreManager();
  106. }
  107. protected StorageVersion getStorageVersion(EntityManager em) {
  108. return getDatastoreManagerForEM(em).getStorageVersion();
  109. }
  110. protected void beginTxn() {
  111. em.getTransaction().begin();
  112. }
  113. protected void commitTxn() {
  114. em.getTransaction().commit();
  115. }
  116. protected void rollbackTxn() {
  117. if (em.getTransaction().isActive()) {
  118. em.getTransaction().rollback();
  119. }
  120. }
  121. protected void switchDatasource(EntityManagerFactoryName name) {
  122. switchDatasource(name, null);
  123. }
  124. protected void switchDatasource(EntityManagerFactoryName name, Map<String, String> props) {
  125. em.close();
  126. if (!cacheManagers() && emf.isOpen()) {
  127. emf.close();
  128. }
  129. if (props == null) {
  130. emf = Persistence.createEntityManagerFactory(name.name());
  131. } else {
  132. emf = Persistence.createEntityManagerFactory(name.name(), props);
  133. }
  134. em = emf.createEntityManager();
  135. }
  136. @SuppressWarnings("deprecation")
  137. public int countForClass(Class<?> clazz) {
  138. String kind = kindForClass(clazz);
  139. return ds.prepare(new Query(kind)).countEntities();
  140. }
  141. protected void deleteAll() {
  142. List<Entity> entities = ds.prepare(new Query().setKeysOnly()).asList(FetchOptions.Builder.withDefaults());
  143. for (Entity entity : entities) {
  144. ds.delete(entity.getKey());
  145. }
  146. }
  147. protected String kindForClass(Class<?> clazz) {
  148. NucleusContext nucContext = ((JPAEntityManagerFactory)emf).getNucleusContext();
  149. MetaDataManager mdm = nucContext.getMetaDataManager();
  150. MappedStoreManager storeMgr = (MappedStoreManager) nucContext.getStoreManager();
  151. ClassLoaderResolver clr = nucContext.getClassLoaderResolver(getClass().getClassLoader());
  152. return EntityUtils.determineKind(
  153. mdm.getMetaDataForClass(
  154. clazz,
  155. nucContext.getClassLoaderResolver(getClass().getClassLoader())),
  156. storeMgr,
  157. clr);
  158. }
  159. protected ExecutionContext getExecutionContext() {
  160. return ((JPAEntityManager)em).getExecutionContext();
  161. }
  162. protected String kindForObject(Object obj) {
  163. return kindForClass(obj.getClass());
  164. }
  165. private boolean cacheManagers() {
  166. return !Boolean.valueOf(System.getProperty("do.not.cache.managers"));
  167. }
  168. interface StartEnd {
  169. void start();
  170. void end();
  171. }
  172. final StartEnd TXN_START_END = new StartEnd() {
  173. public void start() {
  174. beginTxn();
  175. }
  176. public void end() {
  177. commitTxn();
  178. }
  179. };
  180. final StartEnd NEW_EM_START_END = new StartEnd() {
  181. public void start() {
  182. if (!em.isOpen()) {
  183. em = emf.createEntityManager();
  184. }
  185. }
  186. public void end() {
  187. em.close();
  188. }
  189. };
  190. protected DatastoreManager getStoreManager() {
  191. return (DatastoreManager) getExecutionContext().getStoreManager();
  192. }
  193. }