| /** |
| * <copyright> Copyright (c) 2005, 2006, 2007, 2008 Springsite BV (The Netherlands) and others All rights |
| * reserved. This program and the accompanying materials are made available under the terms of the |
| * Eclipse Public License v1.0 which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html Contributors: Martin Taal </copyright> $Id: |
| * HibernateTestStore.java,v 1.16 2007/03/29 15:00:21 mtaal Exp $ |
| */ |
| |
| package org.eclipse.emf.teneo.hibernate.test.stores; |
| |
| import java.io.Serializable; |
| import java.sql.Connection; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.Date; |
| import java.util.List; |
| import java.util.Properties; |
| |
| import javax.persistence.EntityManager; |
| |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| import org.eclipse.emf.common.util.URI; |
| import org.eclipse.emf.ecore.EClass; |
| import org.eclipse.emf.ecore.EClassifier; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.EPackage; |
| import org.eclipse.emf.ecore.EStructuralFeature; |
| import org.eclipse.emf.ecore.resource.Resource; |
| import org.eclipse.emf.ecore.resource.ResourceSet; |
| import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; |
| import org.eclipse.emf.teneo.Constants; |
| import org.eclipse.emf.teneo.DataStore; |
| import org.eclipse.emf.teneo.PackageRegistryProvider; |
| import org.eclipse.emf.teneo.PersistenceOptions; |
| import org.eclipse.emf.teneo.annotations.pannotation.InheritanceType; |
| import org.eclipse.emf.teneo.ecore.EModelResolver; |
| import org.eclipse.emf.teneo.extension.ExtensionManager; |
| import org.eclipse.emf.teneo.hibernate.HbDataStore; |
| import org.eclipse.emf.teneo.hibernate.HbEntityDataStore; |
| import org.eclipse.emf.teneo.hibernate.HbHelper; |
| import org.eclipse.emf.teneo.hibernate.HbSessionDataStore; |
| import org.eclipse.emf.teneo.hibernate.SessionWrapper; |
| import org.eclipse.emf.teneo.hibernate.resource.HbResource; |
| import org.eclipse.emf.teneo.hibernate.resource.HibernateResource; |
| import org.eclipse.emf.teneo.hibernate.test.stores.adapters.HibernateTestDBAdapter; |
| import org.eclipse.emf.teneo.mapping.strategy.EntityNameStrategy; |
| import org.eclipse.emf.teneo.test.stores.AbstractTestStore; |
| import org.eclipse.emf.teneo.test.stores.HsqldbTestDatabaseAdapter; |
| import org.eclipse.emf.teneo.util.AssertUtil; |
| import org.eclipse.emf.teneo.util.EcoreDataTypes; |
| import org.hibernate.FlushMode; |
| import org.hibernate.Session; |
| import org.hibernate.cfg.Environment; |
| |
| import junit.framework.TestCase; |
| |
| /** |
| * The hibernate test store encapsulates the datastore actions to a hibernate store. |
| * |
| * @author <a href="mailto:mtaal@elver.org">Martin Taal</a> |
| * @version $Revision: 1.42 $ |
| */ |
| public class HibernateTestStore extends AbstractTestStore { |
| /** The logger */ |
| private static Log log = LogFactory.getLog(HibernateTestStore.class); |
| |
| public static final String USE_DATASTORE_REGISTRY = "useDataStoreRegistry"; |
| public static final String EPACKAGE_INIT_MODE = "epackageinitmode"; |
| public static final String EPACKAGE_INIT_MODE_SPECIFIED = "specified"; |
| public static final String SPECIFIED_EPACKAGES = "specified_epackages"; |
| public static final String EPACKAGE_INIT_MODE_CLASS = "class"; |
| public static final String EPACKAGE_INIT_MODE_ECORE = "ecore"; |
| public static final String EPACKAGE_INIT_MODE_ECORE_VALUE = "ecorefile"; |
| |
| /** The emf resource set used during the test */ |
| protected ResourceSet resourceSet; |
| |
| /** The EMFDatastore */ |
| private HbDataStore emfDataStore; |
| |
| /** The persistence manager for this test store */ |
| private SessionWrapper sessionWrapper; |
| |
| /** The props used to create it all */ |
| private final Properties props; |
| |
| /** the used epackages */ |
| private EPackage[] epackages; |
| |
| /** The inheritance logic followed */ |
| private final InheritanceType inheritanceType; |
| |
| /** Do ejb3 */ |
| private final boolean ejb3; |
| |
| /** The extensionManager */ |
| private final ExtensionManager extensionManager; |
| |
| /** |
| * Constructor for emf test cases |
| */ |
| public HibernateTestStore(HibernateTestDBAdapter adapter, EPackage[] epackages, Properties props, |
| InheritanceType inheritanceType, boolean ejb3, ExtensionManager extensionManager) { |
| super(adapter); |
| this.props = props; |
| this.epackages = epackages; |
| this.inheritanceType = inheritanceType; |
| this.ejb3 = ejb3; |
| this.extensionManager = extensionManager; |
| init(); |
| } |
| |
| /** Creates/sets the persistence manager */ |
| private void init() { |
| final HibernateTestDBAdapter adapter = (HibernateTestDBAdapter) getDatabaseAdapter(); |
| |
| props.setProperty(PersistenceOptions.INHERITANCE_MAPPING, inheritanceType.getName()); |
| |
| for (EPackage element : epackages) { |
| log.debug("Creating HibernateTeststore for " + element.getName() + " adapter " |
| + adapter.getClass().getName()); |
| |
| cleanUpAuditingAnnotations(element); |
| } |
| |
| setDataStore(); |
| |
| log.debug("HibernateTestStore initialized"); |
| resourceSet = new ResourceSetImpl(); |
| } |
| |
| private void cleanUpAuditingAnnotations(EPackage ePackage) { |
| for (EClassifier eClassifier : ePackage.getEClassifiers()) { |
| if (eClassifier instanceof EClass) { |
| final EClass eClass = (EClass) eClassifier; |
| eClass.getEAnnotations() |
| .remove(eClass.getEAnnotation(Constants.ANNOTATION_SOURCE_AUDITING)); |
| for (EStructuralFeature eFeature : eClass.getEAllStructuralFeatures()) { |
| eFeature.getEAnnotations().remove( |
| eFeature.getEAnnotation(Constants.ANNOTATION_SOURCE_AUDITING)); |
| if (eFeature.getEAnnotation(Constants.ANNOTATION_SOURCE_TENEO_JPA) != null) { |
| eFeature.getEAnnotation(Constants.ANNOTATION_SOURCE_TENEO_JPA).getDetails() |
| .remove(Constants.ANNOTATION_AUDITING_NOT); |
| } |
| } |
| |
| } |
| } |
| } |
| |
| /** Creates a Hibernate property set from the databaseadapter */ |
| private Properties getHibernateProperties(HibernateTestDBAdapter dbadapter) { |
| final Properties props = new Properties(); |
| props.setProperty(Environment.DRIVER, dbadapter.getDbDriver()); |
| props.setProperty(Environment.USER, dbadapter.getDbUser()); |
| props.setProperty(Environment.URL, dbadapter.getDbUrl()); |
| props.setProperty(Environment.PASS, dbadapter.getDbPwd()); |
| props.setProperty(Environment.DIALECT, dbadapter.getDialect()); |
| props.setProperty(Environment.BYTECODE_PROVIDER, "cglib"); |
| props.setProperty(Environment.USE_SECOND_LEVEL_CACHE, "false"); |
| props.setProperty(Environment.GENERATE_STATISTICS, "false"); |
| return props; |
| } |
| |
| /** Sets the emfDataStore */ |
| private void setDataStore() { |
| // currentTimeMillis is added to make it unique |
| if (ejb3) { |
| emfDataStore = new HbEntityDataStore(); // (HbDataStore)HbHelper.INSTANCE. |
| // createRegisterDataStore |
| // (getDatabaseAdapter().getDbName()); |
| } else { |
| emfDataStore = HbHelper.INSTANCE.createRegisterDataStore(getDatabaseAdapter().getDbName()); |
| } |
| emfDataStore.setExtensionManager(extensionManager); |
| emfDataStore.setName(getDatabaseAdapter().getDbName()); |
| |
| // any value is fine |
| if (props.getProperty(USE_DATASTORE_REGISTRY) != null) { |
| PackageRegistryProvider.getInstance().setPackageRegistry(null); |
| emfDataStore.setPackageRegistry(EPackage.Registry.INSTANCE); |
| } else { |
| PackageRegistryProvider.getInstance().setPackageRegistry(EPackage.Registry.INSTANCE); |
| } |
| |
| // set both hibernate and persistence props as we do not know the |
| // difference right now |
| props.putAll(getHibernateProperties((HibernateTestDBAdapter) getDatabaseAdapter())); |
| |
| if (!props.containsKey(PersistenceOptions.JOIN_TABLE_FOR_NON_CONTAINED_ASSOCIATIONS)) { |
| props.setProperty(PersistenceOptions.JOIN_TABLE_FOR_NON_CONTAINED_ASSOCIATIONS, "false"); |
| } |
| |
| // do a special trick for hsqldb, because hsqldb expects all identifiers |
| // to be |
| // escaped or otherwise uppercases them, so uppercase everything |
| // automatically |
| if (getDatabaseAdapter() instanceof HsqldbTestDatabaseAdapter |
| && !props.containsKey(PersistenceOptions.SQL_CASE_STRATEGY)) { |
| props.setProperty(PersistenceOptions.SQL_CASE_STRATEGY, "uppercase"); |
| } |
| |
| if (isEntityManagerStore()) { |
| props.setProperty(PersistenceOptions.ALSO_MAP_AS_CLASS, "true"); |
| } |
| |
| if (!props.containsKey(PersistenceOptions.ENABLE_AUDITING) |
| && !props.containsKey(Constants.ANNOTATION_AUDITING_NOT)) { |
| props.setProperty(PersistenceOptions.ENABLE_AUDITING, "true"); |
| } |
| |
| emfDataStore.setDataStoreProperties(props); |
| |
| if (props.getProperty(EPACKAGE_INIT_MODE) != null) { |
| if (props.getProperty(EPACKAGE_INIT_MODE).compareTo(EPACKAGE_INIT_MODE_SPECIFIED) == 0) { |
| final List<String> clss = Collections.singletonList(props.getProperty(SPECIFIED_EPACKAGES)); |
| emfDataStore.setEPackageClasses(clss); |
| } else if (props.getProperty(EPACKAGE_INIT_MODE).compareTo(EPACKAGE_INIT_MODE_CLASS) == 0) { |
| final List<String> clss = new ArrayList<String>(); |
| for (EPackage epackage : epackages) { |
| clss.add(epackage.getClass().getName()); |
| } |
| emfDataStore.setEPackageClasses(clss); |
| } else if (props.getProperty(EPACKAGE_INIT_MODE).compareTo(EPACKAGE_INIT_MODE_ECORE) == 0) { |
| final List<String> ecores = new ArrayList<String>(); |
| ecores.add(props.getProperty(EPACKAGE_INIT_MODE_ECORE_VALUE)); |
| emfDataStore.setEPackageFiles(ecores); |
| } |
| } else { |
| emfDataStore.setEPackages(epackages); |
| } |
| |
| emfDataStore.initialize(); |
| if (sessionWrapper != null) { |
| refresh(); |
| } else { |
| sessionWrapper = emfDataStore.createSessionWrapper(); |
| sessionWrapper.getHibernateSession().setFlushMode(FlushMode.COMMIT); |
| } |
| } |
| |
| /** Returns the mapping xml */ |
| @Override |
| public String getMappingXML() { |
| return emfDataStore.getMappingXML(); |
| } |
| |
| /** Add an epackage to the list of epackages */ |
| public void addEPackage(EPackage epackage) { |
| EPackage[] newEPacks = new EPackage[epackages.length + 1]; |
| newEPacks[0] = epackage; |
| for (int i = 0; i < epackages.length; i++) { |
| newEPacks[i + 1] = epackages[i]; |
| } |
| epackages = newEPacks; |
| } |
| |
| /** Update the database schema */ |
| public void updateSchema() { |
| // clear the configuration |
| if (emfDataStore instanceof HbSessionDataStore) { |
| ((HbSessionDataStore) emfDataStore).setConfiguration(null); |
| } else { |
| ((HbEntityDataStore) emfDataStore).setConfiguration(null); |
| } |
| emfDataStore.setEPackages(epackages); |
| emfDataStore.initialize(); |
| refresh(); |
| } |
| |
| /** Creates a new persistence manager, actually to clear the cache */ |
| public void refresh() { |
| |
| if (sessionWrapper.isTransactionActive()) { |
| sessionWrapper.rollbackTransaction(); |
| } |
| sessionWrapper.close(); |
| sessionWrapper = emfDataStore.createSessionWrapper(); |
| sessionWrapper.getHibernateSession().setFlushMode(FlushMode.COMMIT); |
| } |
| |
| /** Returns session */ |
| public Session getSession() { |
| final Object obj = sessionWrapper.getSession(); |
| if (obj instanceof Session) { |
| return (Session) obj; |
| } else { |
| return (Session) ((EntityManager) obj).getDelegate(); |
| } |
| } |
| |
| /** Return the sessionwrapper */ |
| public SessionWrapper getSessionWrapper() { |
| return sessionWrapper; |
| } |
| |
| /** Return the entityManager */ |
| public EntityManager getEntityManager() { |
| return (EntityManager) sessionWrapper.getSession(); |
| } |
| |
| /** Returns a new session */ |
| public Session getNewSession() { |
| return emfDataStore.getSessionFactory().openSession(); |
| } |
| |
| /** Begin transaction */ |
| public void beginTransaction() { |
| sessionWrapper.beginTransaction(); |
| } |
| |
| /** Commit transaction */ |
| public void commitTransaction() { |
| sessionWrapper.commitTransaction(); |
| refresh(); |
| } |
| |
| /** Rollback transaction */ |
| public void rollbackTransaction() { |
| if (sessionWrapper.isTransactionActive()) { |
| sessionWrapper.rollbackTransaction(); |
| } |
| refresh(); |
| } |
| |
| /** Store/Makepersistent */ |
| public void store(Object object) { |
| sessionWrapper.saveOrUpdate(object); |
| } |
| |
| /** Deletes an object */ |
| public void deleteObject(Object obj) { |
| sessionWrapper.delete(obj); |
| } |
| |
| /** Test if a delete fails */ |
| public void checkDeleteFails(Class<?> clazz) { |
| checkDelete(clazz, false); // replace class is called in |
| // checkDelete/getObjects |
| } |
| |
| /** Test if a delete fails */ |
| public void checkDeleteSucceeds(Class<?> clazz) { |
| checkDelete(clazz, true); // replace class is called in |
| // CheckDelete/getObjects |
| } |
| |
| /** Query for a class using a field and value pair */ |
| public List<?> query(Class<?> clazz, String field, String value, int checkCount) { |
| // final Class interf = replaceClass(clazz); |
| if (sessionWrapper.isEJB3EntityManager()) { |
| return query("select o from " + getEntityName(clazz) + " o where o." + field + "=\'" + value |
| + "\'", checkCount); |
| } else { |
| return query("from " + getEntityName(clazz) + " where " + field + "=\'" + value + "\'", |
| checkCount); |
| } |
| } |
| |
| /** Queries for an object */ |
| @Override |
| public List<?> query(Object query) { |
| return query(query, -1); |
| } |
| |
| /** Queries for an object and checks the number */ |
| public List<?> query(Object query, int checkCount) { |
| final String qryStr = (String) query; |
| final List<?> result = sessionWrapper.executeQuery(qryStr); |
| |
| if (checkCount > 0) { |
| TestCase.assertTrue("Expected " + checkCount + " object(s) for this query but there are " |
| + result.size() + " object(s) for the query " + qryStr, result.size() == checkCount); |
| } |
| return result; |
| } |
| |
| /** Test if a delete fails */ |
| private void checkDelete(Class<?> clazz, boolean shouldSucceed) { |
| beginTransaction(); |
| final List<?> l = getObjects(clazz); // replace class is called in |
| // getObjects |
| try { |
| for (int i = 0; i < l.size(); i++) { |
| sessionWrapper.delete(l.get(i)); |
| } |
| commitTransaction(); |
| TestCase.assertTrue("The objects of class: " + clazz.getName() |
| + " was deleted while this should not be possible", shouldSucceed); |
| } catch (Exception e) { |
| TestCase.assertTrue("The objects of class: " + clazz.getName() |
| + " was not deleted while this should be possible", !shouldSucceed); |
| if (sessionWrapper.isTransactionActive()) { |
| rollbackTransaction(); |
| } |
| refresh(); |
| } |
| } |
| |
| /** |
| * Return an object of a certain class, there should only be one in the databases |
| */ |
| @Override |
| @SuppressWarnings("unchecked") |
| public <T> T getObject(Class<T> clazz) { |
| List<?> l = getObjects(clazz); // replace class is called in getObjects |
| TestCase.assertTrue("There are " + l.size() |
| + " object(s) of this class in the datastore, 1 was expected, class: " + clazz.getName(), |
| l.size() == 1); |
| return (T) l.get(0); |
| } |
| |
| public Object getObject(String entityName, Serializable id) { |
| return sessionWrapper.get(entityName, id); |
| } |
| |
| /** Returns a list of object of a certain class */ |
| @SuppressWarnings("unchecked") |
| public <T> List<T> getObjects(Class<T> clazz) { |
| // final Class concrete = replaceClass(clazz); |
| if (sessionWrapper.isEJB3EntityManager()) { |
| return (List<T>) sessionWrapper.executeQuery("select o from " + getEntityName(clazz) + " o"); |
| } else { |
| return (List<T>) sessionWrapper.executeQuery("FROM " + getEntityName(clazz)); |
| } |
| } |
| |
| /** Test the amount of objects of a certain class in the db */ |
| @Override |
| public void checkNumber(Class<?> clazz, int count) { |
| final List<?> list = getObjects(clazz); |
| TestCase.assertTrue("Expected " + count + " object(s) but there are " + list.size() |
| + " object(s) of this class in the datastore: " + clazz.getName(), list.size() == count); |
| } |
| |
| /** Flushes all updates to the underlying datastore */ |
| public void flush() { |
| sessionWrapper.flush(); |
| } |
| |
| /** Is called just before the test */ |
| @Override |
| public void setUp() { |
| |
| } |
| |
| /** |
| * Is called just after the test, the dropStore parameter can be used to prevent dropping the |
| * database when an error |
| */ |
| @Override |
| public void doTearDown() { |
| AssertUtil.assertTrue("Transaction is still active at end of test", |
| !sessionWrapper.isTransactionActive()); |
| |
| if (sessionWrapper.isTransactionActive()) { |
| rollbackTransaction(); |
| } |
| |
| sessionWrapper.close(); |
| |
| HbHelper.INSTANCE.closeAll(); |
| |
| if (!donotDrop) { |
| dropDatabase(); |
| } |
| } |
| |
| /** Returns true if the transaction is still active */ |
| public boolean transactionActive() { |
| return sessionWrapper.isTransactionActive(); |
| } |
| |
| /** Base method to get a resource belonging to the pmf of this test case */ |
| @Override |
| public Resource getResource() { |
| return getResource(null); |
| } |
| |
| /** Base method to get a resource belonging to the session of this test case */ |
| public Resource getResource(String extraParam) { |
| String uriStr = "hibernate://?" + HibernateResource.DS_NAME_PARAM + "=" |
| + emfDataStore.getName(); |
| |
| if (extraParam != null) { |
| uriStr += "&" + extraParam; |
| } |
| final URI uri = URI.createURI(uriStr); |
| log.debug("Getting resource using uri: " + uri.toString()); |
| final Resource res = resourceSet.createResource(uri); |
| assert (res instanceof HbResource); |
| return res; |
| } |
| |
| /** |
| * Replaces a passed EMF Interface by its concrete class private Class replaceClass(Class |
| * interfaze) { if (!interfaze.isInterface()) return interfaze; if |
| * (!EObject.class.isAssignableFrom(interfaze)) return interfaze; return |
| * HibernateHelper.INSTANCE.getInstanceClass(interfaze); } |
| */ |
| |
| /** Gets the referedto list */ |
| public Object[] getCrossReferencers(EObject obj, boolean container) { |
| if (container) { |
| return new Object[] { obj.eContainer() }; |
| // final EObject eobj = |
| // ((HbDataStore)emfDataStore).getContainer(session, obj); |
| // if (eobj == null) |
| // { |
| // return new EObject[0]; |
| // } |
| // return new EObject[] {eobj}; |
| } else { |
| return emfDataStore.getCrossReferencers(sessionWrapper, obj); |
| } |
| } |
| |
| /** Gets the container list */ |
| @Override |
| public boolean setContainer(EObject obj) { |
| return true; |
| } |
| |
| /** Refreshes the object from the datastore */ |
| public void refresh(Object obj) { |
| sessionWrapper.refresh(obj); |
| } |
| |
| public Object merge(Object object) { |
| return sessionWrapper.merge(object); |
| } |
| |
| /** Check inheritance strategy */ |
| public boolean isInheritanceStrategy(Class<?> cls, InheritanceType strategy) { |
| return sessionWrapper.isInheritanceStrategy(cls, strategy); |
| } |
| |
| /** Gets a database connection using the adapters connection info */ |
| public Connection getConnection() { |
| return getDatabaseAdapter().getConnection(); |
| } |
| |
| /** Returns the query name to use for the instance */ |
| private String getEntityName(Class<?> clazz) { |
| final EModelResolver emodelResolver = EModelResolver.instance(); |
| final EClass eclass = emodelResolver.getEClass(clazz); |
| return getDataStore().getExtensionManager().getExtension(EntityNameStrategy.class) |
| .toEntityName(eclass); |
| } |
| |
| /** |
| * @return the emfDataStore |
| */ |
| public HbDataStore getEmfDataStore() { |
| return emfDataStore; |
| } |
| |
| /** Return the datastore */ |
| public DataStore getDataStore() { |
| return getEmfDataStore(); |
| } |
| |
| /** |
| * @return the inheritanceType |
| */ |
| public InheritanceType getInheritanceType() { |
| return inheritanceType; |
| } |
| |
| /** Is this a hibernate test store */ |
| @Override |
| public boolean isHibernateTestStore() { |
| return true; |
| } |
| |
| public boolean isEntityManagerStore() { |
| return ejb3; |
| } |
| |
| /** Set the xmlgregoriancalendar date */ |
| public Object getDate(Date date) { |
| return EcoreDataTypes.INSTANCE.getXMLGregorianCalendar(date); |
| } |
| } |