001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */
019: package org.apache.openjpa.persistence.test;
020:
021: import java.lang.reflect.Modifier;
022: import java.util.ArrayList;
023: import java.util.Iterator;
024: import java.util.List;
025: import java.util.Map;
026: import java.util.HashMap;
027: import javax.persistence.EntityManager;
028: import javax.persistence.EntityManagerFactory;
029: import javax.persistence.Persistence;
030:
031: import junit.framework.TestCase;
032: import junit.framework.TestResult;
033: import org.apache.openjpa.kernel.AbstractBrokerFactory;
034: import org.apache.openjpa.kernel.Broker;
035: import org.apache.openjpa.meta.ClassMetaData;
036: import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI;
037: import org.apache.openjpa.persistence.JPAFacadeHelper;
038:
039: /**
040: * Base test class providing persistence utilities.
041: */
042: public abstract class PersistenceTestCase extends TestCase {
043:
044: /**
045: * Marker object you an pass to {@link #setUp} to indicate that the
046: * database tables should be cleared.
047: */
048: protected static final Object CLEAR_TABLES = new Object();
049:
050: /**
051: * The {@link TestResult} instance for the current test run.
052: */
053: protected TestResult testResult;
054:
055: /**
056: * Create an entity manager factory. Put {@link #CLEAR_TABLES} in
057: * this list to tell the test framework to delete all table contents
058: * before running the tests.
059: *
060: * @param props list of persistent types used in testing and/or
061: * configuration values in the form key,value,key,value...
062: */
063: protected OpenJPAEntityManagerFactorySPI createEMF(Object... props) {
064: return createNamedEMF(getPersistenceUnitName(), props);
065: }
066:
067: /**
068: * The name of the persistence unit that this test class should use
069: * by default. This defaults to "test".
070: */
071: protected String getPersistenceUnitName() {
072: return "test";
073: }
074:
075: /**
076: * Create an entity manager factory for persistence unit <code>pu</code>.
077: * Put {@link #CLEAR_TABLES} in
078: * this list to tell the test framework to delete all table contents
079: * before running the tests.
080: *
081: * @param props list of persistent types used in testing and/or
082: * configuration values in the form key,value,key,value...
083: */
084: protected OpenJPAEntityManagerFactorySPI createNamedEMF(String pu,
085: Object... props) {
086: Map map = new HashMap(System.getProperties());
087: List<Class> types = new ArrayList<Class>();
088: boolean prop = false;
089: for (int i = 0; i < props.length; i++) {
090: if (prop) {
091: map.put(props[i - 1], props[i]);
092: prop = false;
093: } else if (props[i] == CLEAR_TABLES) {
094: map
095: .put(
096: "openjpa.jdbc.SynchronizeMappings",
097: "buildSchema(ForeignKeys=true,"
098: + "SchemaAction='add,deleteTableContents')");
099: } else if (props[i] instanceof Class)
100: types.add((Class) props[i]);
101: else if (props[i] != null)
102: prop = true;
103: }
104:
105: if (!types.isEmpty()) {
106: StringBuffer buf = new StringBuffer();
107: for (Class c : types) {
108: if (buf.length() > 0)
109: buf.append(";");
110: buf.append(c.getName());
111: }
112: map.put("openjpa.MetaDataFactory", "jpa(Types="
113: + buf.toString() + ")");
114: }
115:
116: return (OpenJPAEntityManagerFactorySPI) Persistence
117: .createEntityManagerFactory(pu, map);
118: }
119:
120: @Override
121: public void run(TestResult testResult) {
122: this .testResult = testResult;
123: super .run(testResult);
124: }
125:
126: @Override
127: public void tearDown() throws Exception {
128: try {
129: super .tearDown();
130: } catch (Exception e) {
131: // if a test failed, swallow any exceptions that happen
132: // during tear-down, as these just mask the original problem.
133: if (testResult.wasSuccessful())
134: throw e;
135: }
136: }
137:
138: /**
139: * Safely close the given factory.
140: */
141: protected boolean closeEMF(EntityManagerFactory emf) {
142: if (emf == null || !emf.isOpen())
143: return false;
144:
145: closeAllOpenEMs(emf);
146: emf.close();
147: return !emf.isOpen();
148: }
149:
150: /**
151: * Closes all open entity managers after first rolling back any open transactions
152: */
153: protected void closeAllOpenEMs(EntityManagerFactory emf) {
154: if (emf == null || !emf.isOpen())
155: return;
156:
157: for (Iterator iter = ((AbstractBrokerFactory) JPAFacadeHelper
158: .toBrokerFactory(emf)).getOpenBrokers().iterator(); iter
159: .hasNext();) {
160: Broker b = (Broker) iter.next();
161: if (b != null && !b.isClosed()) {
162: EntityManager em = JPAFacadeHelper.toEntityManager(b);
163: if (em.getTransaction().isActive())
164: em.getTransaction().rollback();
165: em.close();
166: }
167: }
168: }
169:
170: /**
171: * Delete all instances of the given types using bulk delete queries,
172: * but do not close any open entity managers.
173: */
174: protected void clear(EntityManagerFactory emf, Class... types) {
175: if (emf == null || types.length == 0)
176: return;
177:
178: List<ClassMetaData> metas = new ArrayList<ClassMetaData>(
179: types.length);
180: for (Class c : types) {
181: ClassMetaData meta = JPAFacadeHelper.getMetaData(emf, c);
182: if (meta != null)
183: metas.add(meta);
184: }
185: clear(emf, false, metas
186: .toArray(new ClassMetaData[metas.size()]));
187: }
188:
189: /**
190: * Delete all instances of the persistent types registered with the given
191: * factory using bulk delete queries, after first closing all open entity
192: * managers (and rolling back any open transactions).
193: */
194: protected void clear(EntityManagerFactory emf) {
195: if (emf == null)
196: return;
197: clear(emf, true, ((OpenJPAEntityManagerFactorySPI) emf)
198: .getConfiguration().getMetaDataRepositoryInstance()
199: .getMetaDatas());
200: }
201:
202: /**
203: * Delete all instances of the given types using bulk delete queries.
204: * @param closeEMs TODO
205: */
206: private void clear(EntityManagerFactory emf, boolean closeEMs,
207: ClassMetaData... types) {
208: if (emf == null || types.length == 0)
209: return;
210:
211: // prevent deadlock by closing the open entity managers
212: // and rolling back any open transactions
213: // before issuing delete statements on a new entity manager.
214: if (closeEMs)
215: closeAllOpenEMs(emf);
216:
217: EntityManager em = emf.createEntityManager();
218: em.getTransaction().begin();
219: for (ClassMetaData meta : types) {
220: if (!meta.isMapped()
221: || meta.isEmbeddedOnly()
222: || Modifier.isAbstract(meta.getDescribedType()
223: .getModifiers()))
224: continue;
225: em.createQuery("DELETE FROM " + meta.getTypeAlias() + " o")
226: .executeUpdate();
227: }
228: em.getTransaction().commit();
229: em.close();
230: }
231:
232: /**
233: * Return the entity name for the given type.
234: */
235: protected String entityName(EntityManagerFactory emf, Class c) {
236: ClassMetaData meta = JPAFacadeHelper.getMetaData(emf, c);
237: return (meta == null) ? null : meta.getTypeAlias();
238: }
239:
240: public static void assertNotEquals(Object o1, Object o2) {
241: if (o1 == o2)
242: fail("expected args to be different; were the same instance.");
243: else if (o1 == null || o2 == null)
244: return;
245: else if (o1.equals(o2))
246: fail("expected args to be different; compared equal.");
247: }
248: }
|