/tests_bugs/com/google/appengine/datanucleus/bugs/jpa/JPABugTestCase.java
Java | 211 lines | 154 code | 28 blank | 29 comment | 17 complexity | 007253bb6a39f6cbc57f13342202be95 MD5 | raw file
1/********************************************************************** 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.bugs.jpa; 17 18import com.google.appengine.api.datastore.DatastoreService; 19import com.google.appengine.api.datastore.DatastoreServiceFactory; 20import com.google.appengine.api.datastore.Query; 21import com.google.appengine.datanucleus.DatastoreManager; 22import com.google.appengine.datanucleus.bugs.DatastoreTestCase; 23import com.google.appengine.datanucleus.EntityUtils; 24 25import org.datanucleus.ClassLoaderResolver; 26import org.datanucleus.NucleusContext; 27import org.datanucleus.api.jpa.JPAEntityManager; 28import org.datanucleus.api.jpa.JPAEntityManagerFactory; 29import org.datanucleus.metadata.MetaDataManager; 30import org.datanucleus.ExecutionContext; 31import org.datanucleus.store.mapped.MappedStoreManager; 32 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 JPABugTestCase 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 } 84 85 /** 86 * By default we use a datasource that requires txns. 87 * Override this if your test needs to use a different instance. 88 */ 89 protected EntityManagerFactoryName getEntityManagerFactoryName() { 90 return EntityManagerFactoryName.transactional_ds_non_transactional_ops_not_allowed; 91 } 92 93 @Override 94 protected void tearDown() throws Exception { 95 try { 96 if (em.isOpen()) { 97 if (em.getTransaction().isActive()) { 98 em.getTransaction().rollback(); 99 } 100 em.close(); 101 } 102 em = null; 103 // see if anybody closed any of our emfs and if so just remove them from the cache - 104 // we'll rebuild it the next time it's needed. 105 for (Map.Entry<EntityManagerFactoryName, EntityManagerFactory> entry : emfCache.get().entrySet()) { 106 if (!entry.getValue().isOpen()) { 107 emfCache.get().remove(entry.getKey()); 108 } 109 } 110 if (!cacheManagers() && emf.isOpen()) { 111 emf.close(); 112 } 113 emf = null; 114 } finally { 115 super.tearDown(); 116 } 117 } 118 119 protected void beginTxn() { 120 em.getTransaction().begin(); 121 } 122 123 protected void commitTxn() { 124 em.getTransaction().commit(); 125 } 126 127 protected void rollbackTxn() { 128 if (em.getTransaction().isActive()) { 129 em.getTransaction().rollback(); 130 } 131 } 132 133 protected void switchDatasource(EntityManagerFactoryName name) { 134 switchDatasource(name, null); 135 } 136 137 protected void switchDatasource(EntityManagerFactoryName name, Map<String, String> props) { 138 em.close(); 139 if (!cacheManagers() && emf.isOpen()) { 140 emf.close(); 141 } 142 if (props == null) { 143 emf = Persistence.createEntityManagerFactory(name.name()); 144 } else { 145 emf = Persistence.createEntityManagerFactory(name.name(), props); 146 } 147 em = emf.createEntityManager(); 148 } 149 150 @SuppressWarnings("deprecation") 151 public int countForClass(Class<?> clazz) { 152 String kind = kindForClass(clazz); 153 return ds.prepare(new Query(kind)).countEntities(); 154 } 155 156 protected String kindForClass(Class<?> clazz) { 157 NucleusContext nucContext = ((JPAEntityManagerFactory)emf).getNucleusContext(); 158 MetaDataManager mdm = nucContext.getMetaDataManager(); 159 MappedStoreManager storeMgr = (MappedStoreManager) nucContext.getStoreManager(); 160 ClassLoaderResolver clr = nucContext.getClassLoaderResolver(getClass().getClassLoader()); 161 return EntityUtils.determineKind( 162 mdm.getMetaDataForClass( 163 clazz, 164 nucContext.getClassLoaderResolver(getClass().getClassLoader())), 165 storeMgr, 166 clr); 167 } 168 169 protected ExecutionContext getExecutionContext() { 170 return ((JPAEntityManager)em).getExecutionContext(); 171 } 172 173 protected String kindForObject(Object obj) { 174 return kindForClass(obj.getClass()); 175 } 176 177 private boolean cacheManagers() { 178 return !Boolean.valueOf(System.getProperty("do.not.cache.managers")); 179 } 180 181 interface StartEnd { 182 void start(); 183 void end(); 184 } 185 186 final StartEnd TXN_START_END = new StartEnd() { 187 public void start() { 188 beginTxn(); 189 } 190 191 public void end() { 192 commitTxn(); 193 } 194 }; 195 196 final StartEnd NEW_EM_START_END = new StartEnd() { 197 public void start() { 198 if (!em.isOpen()) { 199 em = emf.createEntityManager(); 200 } 201 } 202 203 public void end() { 204 em.close(); 205 } 206 }; 207 208 protected DatastoreManager getStoreManager() { 209 return (DatastoreManager) getExecutionContext().getStoreManager(); 210 } 211}