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