| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.apache.openjpa.slice; |
| |
| import java.lang.reflect.Modifier; |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.HashMap; |
| import javax.persistence.EntityManager; |
| import javax.persistence.EntityManagerFactory; |
| import javax.persistence.Persistence; |
| |
| import junit.framework.TestCase; |
| import junit.framework.TestResult; |
| import org.apache.openjpa.kernel.AbstractBrokerFactory; |
| import org.apache.openjpa.kernel.Broker; |
| import org.apache.openjpa.meta.ClassMetaData; |
| import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI; |
| import org.apache.openjpa.persistence.JPAFacadeHelper; |
| |
| /** |
| * Base test class providing persistence utilities. |
| */ |
| public abstract class PersistenceTestCase |
| extends TestCase { |
| |
| /** |
| * Marker object you an pass to {@link #setUp} to indicate that the |
| * database tables should be cleared. |
| */ |
| protected static final Object CLEAR_TABLES = new Object(); |
| |
| /** |
| * The {@link TestResult} instance for the current test run. |
| */ |
| protected TestResult testResult; |
| |
| /** |
| * Create an entity manager factory. Put {@link #CLEAR_TABLES} in |
| * this list to tell the test framework to delete all table contents |
| * before running the tests. |
| * |
| * @param props list of persistent types used in testing and/or |
| * configuration values in the form key,value,key,value... |
| */ |
| protected OpenJPAEntityManagerFactorySPI createEMF(Object... props) { |
| return createNamedEMF(getPersistenceUnitName(), props); |
| } |
| |
| /** |
| * The name of the persistence unit that this test class should use |
| * by default. This defaults to "test". |
| */ |
| protected String getPersistenceUnitName() { |
| return "test"; |
| } |
| |
| /** |
| * Create an entity manager factory for persistence unit <code>pu</code>. |
| * Put {@link #CLEAR_TABLES} in |
| * this list to tell the test framework to delete all table contents |
| * before running the tests. |
| * |
| * @param props list of persistent types used in testing and/or |
| * configuration values in the form key,value,key,value... |
| */ |
| protected OpenJPAEntityManagerFactorySPI createNamedEMF(String pu, |
| Object... props) { |
| Map map = new HashMap(System.getProperties()); |
| List<Class> types = new ArrayList<Class>(); |
| boolean prop = false; |
| for (int i = 0; i < props.length; i++) { |
| if (prop) { |
| map.put(props[i - 1], props[i]); |
| prop = false; |
| } else if (props[i] == CLEAR_TABLES) { |
| map.put("openjpa.jdbc.SynchronizeMappings", |
| "buildSchema(ForeignKeys=true," |
| + "SchemaAction='add,deleteTableContents')"); |
| } else if (props[i] instanceof Class) |
| types.add((Class) props[i]); |
| else if (props[i] != null) |
| prop = true; |
| } |
| |
| if (!types.isEmpty()) { |
| StringBuffer buf = new StringBuffer(); |
| for (Class c : types) { |
| if (buf.length() > 0) |
| buf.append(";"); |
| buf.append(c.getName()); |
| } |
| map.put("openjpa.MetaDataFactory", |
| "jpa(Types=" + buf.toString() + ")"); |
| } |
| |
| return (OpenJPAEntityManagerFactorySPI) Persistence. |
| createEntityManagerFactory(pu, map); |
| } |
| |
| @Override |
| public void run(TestResult testResult) { |
| this.testResult = testResult; |
| super.run(testResult); |
| } |
| |
| @Override |
| public void tearDown() throws Exception { |
| try { |
| super.tearDown(); |
| } catch (Exception e) { |
| // if a test failed, swallow any exceptions that happen |
| // during tear-down, as these just mask the original problem. |
| if (testResult.wasSuccessful()) |
| throw e; |
| } |
| } |
| |
| /** |
| * Safely close the given factory. |
| */ |
| protected boolean closeEMF(EntityManagerFactory emf) { |
| if (emf == null || !emf.isOpen()) |
| return false; |
| |
| closeAllOpenEMs(emf); |
| emf.close(); |
| return !emf.isOpen(); |
| } |
| |
| /** |
| * Closes all open entity managers after first rolling back any open transactions |
| */ |
| protected void closeAllOpenEMs(EntityManagerFactory emf) { |
| if (emf == null || !emf.isOpen()) |
| return; |
| |
| for (Iterator iter = ((AbstractBrokerFactory) JPAFacadeHelper |
| .toBrokerFactory(emf)).getOpenBrokers().iterator(); |
| iter.hasNext(); ) { |
| Broker b = (Broker) iter.next(); |
| if (b != null && !b.isClosed()) { |
| EntityManager em = JPAFacadeHelper.toEntityManager(b); |
| if (em.getTransaction().isActive()) |
| em.getTransaction().rollback(); |
| em.close(); |
| } |
| } |
| } |
| |
| /** |
| * Delete all instances of the given types using bulk delete queries, |
| * but do not close any open entity managers. |
| */ |
| protected void clear(EntityManagerFactory emf, Class... types) { |
| if (emf == null || types.length == 0) |
| return; |
| |
| List<ClassMetaData> metas = new ArrayList<ClassMetaData>(types.length); |
| for (Class c : types) { |
| ClassMetaData meta = JPAFacadeHelper.getMetaData(emf, c); |
| if (meta != null) |
| metas.add(meta); |
| } |
| clear(emf, false, metas.toArray(new ClassMetaData[metas.size()])); |
| } |
| |
| /** |
| * Delete all instances of the persistent types registered with the given |
| * factory using bulk delete queries, after first closing all open entity |
| * managers (and rolling back any open transactions). |
| */ |
| protected void clear(EntityManagerFactory emf) { |
| if (emf == null) |
| return; |
| clear(emf, true, ((OpenJPAEntityManagerFactorySPI) emf).getConfiguration(). |
| getMetaDataRepositoryInstance().getMetaDatas()); |
| } |
| |
| /** |
| * Delete all instances of the given types using bulk delete queries. |
| * @param closeEMs TODO |
| */ |
| private void clear(EntityManagerFactory emf, boolean closeEMs, ClassMetaData... types) { |
| if (emf == null || types.length == 0) |
| return; |
| |
| // prevent deadlock by closing the open entity managers |
| // and rolling back any open transactions |
| // before issuing delete statements on a new entity manager. |
| if (closeEMs) |
| closeAllOpenEMs(emf); |
| |
| EntityManager em = emf.createEntityManager(); |
| em.getTransaction().begin(); |
| for (ClassMetaData meta : types) { |
| if (!meta.isMapped() || meta.isEmbeddedOnly() |
| || Modifier.isAbstract(meta.getDescribedType().getModifiers())) |
| continue; |
| // em.createQuery("DELETE FROM " + meta.getTypeAlias() + " o"). |
| // executeUpdate(); |
| } |
| em.getTransaction().commit(); |
| em.close(); |
| } |
| |
| /** |
| * Return the entity name for the given type. |
| */ |
| protected String entityName(EntityManagerFactory emf, Class c) { |
| ClassMetaData meta = JPAFacadeHelper.getMetaData(emf, c); |
| return (meta == null) ? null : meta.getTypeAlias(); |
| } |
| |
| public static void assertNotEquals(Object o1, Object o2) { |
| if (o1 == o2) |
| fail("expected args to be different; were the same instance."); |
| else if (o1 == null || o2 == null) |
| return; |
| else if (o1.equals(o2)) |
| fail("expected args to be different; compared equal."); |
| } |
| } |