Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2008, Unitils.org
*
* Licensed 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.unitils.orm.common;
import org.unitils.core.Module;
import org.unitils.core.TestListener;
import org.unitils.core.Unitils;
import org.unitils.core.UnitilsException;
import org.unitils.core.util.ResourceConfigLoader;
import org.unitils.database.DatabaseModule;
import org.unitils.database.util.Flushable;
import org.unitils.orm.common.spring.OrmSpringSupport;
import org.unitils.orm.common.util.ConfiguredOrmPersistenceUnit;
import org.unitils.orm.common.util.OrmConfig;
import org.unitils.orm.common.util.OrmPersistenceUnitLoader;
import org.unitils.orm.jpa.annotation.JpaEntityManagerFactory;
import org.unitils.util.AnnotationUtils;
import static org.unitils.util.AnnotationUtils.getFieldsAnnotatedWith;
import static org.unitils.util.AnnotationUtils.getMethodsAnnotatedWith;
import static org.unitils.util.ReflectionUtils.createInstanceOfType;
import static org.unitils.util.ReflectionUtils.setFieldAndSetterValue;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
/**
* Base module defining common behavior for a module that provides object relational mapping support for tests.
* This abstract module takes into account loading and caching of persistence units. A persistence unit
* can be configured using unitils annotations or in a spring ApplicationContext.
* The persistence unit is injected into the test object's annotated fields. This module also supports
* flushing of the active persistence context.
*
* @author Filip Neven
* @author Tim Ducheyne
* @param Type of the ORM persistence unit
* @param Type of the ORM persistence context
* @param Type of the implementation specific configuration object
* @param Type of the annotation used for configuring and injecting the persistence unit
* @param Type of the value object extending {@link OrmConfig} that contains all unitils specific persitence unit configuration
* @param Subtype of {@link OrmPersistenceUnitLoader} that loads the persistence unit based on the ORM_CONFIG.
*/
abstract public class OrmModule> implements Module, Flushable {
/**
* Class that loads the persistence unit configuration
*/
protected ORM_PERSISTENCE_UNIT_CONFIG_LOADER persistenceUnitConfigLoader;
/**
* Class that loads the persistence unit, given an object extending {@link OrmConfig}
*/
protected OrmPersistenceUnitLoader ormPersistenceUnitLoader;
/**
* Cache for persistence units and its configuration. We use this to make sure that for tests that use the same
* persistence unit configuration, the same persistence unit instance is reused
*/
protected Map> configuredOrmPersistenceUnitCache
= new HashMap>();
/**
* Support class that enables getting a configured persistence unit from a spring ApplicationContext configured in
* unitils. If the spring module is not enabled, this object is null.
*/
protected OrmSpringSupport ormSpringSupport;
protected String databaseName;
public void init(Properties configuration) {
persistenceUnitConfigLoader = createOrmConfigLoader();
ormPersistenceUnitLoader = createOrmPersistenceUnitLoader();
}
public void afterInit() {
initOrmSpringSupport();
}
/**
* @return A new instance of the {@link ResourceConfigLoader} that scans a test object for a persistence
* unit configuration, and returns a specific subtype of {@link OrmConfig} that wraps this configuration
*/
abstract protected ORM_PERSISTENCE_UNIT_CONFIG_LOADER createOrmConfigLoader();
/**
* @return The class of the annotation that is used for configuring and requesting injection of the
* persistence unit
*/
abstract protected Class getPersistenceUnitConfigAnnotationClass();
/**
* @return The type of the persistence unit
*/
abstract protected Class getPersistenceUnitClass();
/**
* @return A new instance of {@link OrmPersistenceUnitLoader} that can create a new persistence unit
* based on an {@link OrmConfig} object
*/
abstract protected OrmPersistenceUnitLoader createOrmPersistenceUnitLoader();
/**
* @return The fully qualified classname of the concrete implementation of {@link OrmSpringSupport} that
* is used by the ORM module implementation
*/
abstract protected String getOrmSpringSupportImplClassName();
/**
* Returns a configured ORM persistence unit for the given test object. This persistence unit can be either configured
* in a Spring ApplicationContext or by using the annotation that is applicable for the ORM implementation.
* An exception is thrown if no persistence unit is configured. If possible, a cached instance is returned that was
* created during a previous test.
*
* @param testObject The test instance, not null
* @return The ORM persistence unit, not null
*/
public ORM_PERSISTENCE_UNIT getPersistenceUnit(Object testObject) {
ConfiguredOrmPersistenceUnit configuredPersistenceUnit = getConfiguredPersistenceUnit(testObject);
return configuredPersistenceUnit.getOrmPersistenceUnit();
}
/**
* Returns the ORM implementation specific configuration object. This object cannot be used for configuration of a
* persistence units anymore, but may be useful for implementing some specific behavior, like the entity-database
* mapping test
*
* @param testObject The test instance, not null
* @return The ORM implementation specific configuration object
*/
public PROVIDER_CONFIGURATION_OBJECT getConfigurationObject(Object testObject) {
ConfiguredOrmPersistenceUnit configuredPersistenceUnit = getConfiguredPersistenceUnit(testObject);
return configuredPersistenceUnit.getOrmConfigurationObject();
}
/**
* Returns a wrapper for the persistence unit and any implementation specific configuration object for the given test
* object. This persistence unit can be either configured in a Spring ApplicationContext or by using the
* annotation that is applicable for the ORM implementation. An exception is thrown if no persistence unit is configured.
* If possible, a cached instance is returned that was created during a previous test.
*
* @param testObject The test instance, not null
* @return The persistence unit, not null
*/
protected ConfiguredOrmPersistenceUnit getConfiguredPersistenceUnit(Object testObject) {
// If a persistence unit was configured in the spring ApplicationContext for this test object, we return
// this one. Notice that in that case, no extra caching is done. This is not needed because the ApplicationContext
// is already cached, and the ApplicationContext makes sure that the same persistence unit instance is always returned.
if (ormSpringSupport != null && ormSpringSupport.isPersistenceUnitConfiguredInSpring(testObject)) {
return ormSpringSupport.getConfiguredPersistenceUnit(testObject);
}
// Check if a persistence unit configuration can be found on the test class. If not, throw an exception
ORM_CONFIG persistenceUnitConfig = getPersistenceUnitConfig(testObject);
if (persistenceUnitConfig == null) {
throw new UnitilsException("Could not find a configuring @" + getPersistenceUnitConfigAnnotationClass().getSimpleName() + " annotation or custom config method");
}
// Look for a cached instance. If not available, a new instance is created and added to the cache
ConfiguredOrmPersistenceUnit configuredPersistenceUnit = configuredOrmPersistenceUnitCache.get(persistenceUnitConfig);
if (configuredPersistenceUnit == null) {
configuredPersistenceUnit = ormPersistenceUnitLoader.getConfiguredOrmPersistenceUnit(testObject, persistenceUnitConfig);
configuredOrmPersistenceUnitCache.put(persistenceUnitConfig, configuredPersistenceUnit);
getDatabaseModule().activateTransactionIfNeeded();
}
return configuredPersistenceUnit;
}
/*protected boolean isConfiguredPersistenceUnitActive(Object testObject) {
if (ormSpringSupport != null && ormSpringSupport.isPersistenceUnitConfiguredInSpring(testObject)) {
return true;
}
return configuredOrmPersistenceUnitCache.containsKey(testObject);
}*/
/**
* @param testObject The test instance, not null
* @return The persistence unit configuration for this test class. Null if no configuration is available
*/
protected ORM_CONFIG getPersistenceUnitConfig(Object testObject) {
return persistenceUnitConfigLoader.loadResourceConfig(testObject);
}
/**
* Indicates whether an ORM persistence unit has been configured for the given testObject. This persistence
* unit can be either configured in a Spring ApplicationContext or by using the annotation that
* is applicable for the ORM implementation.
*
* @param testObject The test instance, not null
* @return true if a EntityManagerFactory has been configured, false otherwise
*/
public boolean isPersistenceUnitConfiguredFor(Object testObject) {
return (ormSpringSupport != null && ormSpringSupport.isPersistenceUnitConfiguredInSpring(testObject) || getPersistenceUnitConfig(testObject) != null);
}
/**
* Returns an implementation specific persistence context, which is associated with the current transaction.
*
* @param testObject The test instance, not null
* @return A persistence context, not null
*/
public ORM_PERSISTENCE_CONTEXT getPersistenceContext(Object testObject) {
// If no EntityManagerFactory was configured in unitils, no EntityManagers can be created
if (!isPersistenceUnitConfiguredFor(testObject)) {
throw new UnitilsException("No persistence unit has been configured for this test class. Make sure you either "
+ "configure one in the spring ApplicationContext for this class, or by using the annotation @"
+ getPersistenceUnitConfigAnnotationClass().getSimpleName());
}
return doGetPersistenceContext(testObject);
}
/**
* Implementations of this method must return a persistence context object, and must be associated with the
* current transaction active in unitils. The implementation can presume that a persistence unit is available,
* so the method may not return null;
*
* @param testObject The test instance, not null
* @return An implementation specific persistence context, not null
*/
abstract protected ORM_PERSISTENCE_CONTEXT doGetPersistenceContext(Object testObject);
/**
* The currently active persistence context, if any. This method will not create a new persistence context,
* it will only return something if a persistence context has previously been requested within the current
* transaction.
*
* @param testObject The test instance, not null
* @return The currently active persistence context, if any
*/
protected ORM_PERSISTENCE_CONTEXT getActivePersistenceContext(Object testObject) {
// If no EntityManagerFactory was configured in unitils, there are no open EntityManagers
if (!isPersistenceUnitConfiguredFor(testObject)) {
return null;
}
return doGetActivePersistenceContext(testObject);
}
/**
* Implementations of this method must return the persistence context object that is associated with the current
* transaction, if any. The implementation can presume that a persistence unit is available. If no persistence
* context is currently active, null is returned.
*
* @param testObject The test instance, not null
* @return The currently active persistence context, if any
*/
abstract protected ORM_PERSISTENCE_CONTEXT doGetActivePersistenceContext(Object testObject);
/**
* Flushes all pending updates to the database. This method is useful when the effect
* of updates needs to be checked directly on the database, without going through the persistence unit
*
* @param testObject The test instance, not null
*/
public void flushDatabaseUpdates(Object testObject) {
ORM_PERSISTENCE_CONTEXT activePersistenceContext = getActivePersistenceContext(testObject);
if (activePersistenceContext != null) {
flushOrmPersistenceContext(activePersistenceContext);
}
}
/**
* Flushes all pending update, using the given active persistence context
*
* @param activePersistenceContext Active persistence context, associated with the current transaction, not null
*/
abstract protected void flushOrmPersistenceContext(ORM_PERSISTENCE_CONTEXT activePersistenceContext);
/**
* Injects the persistence unit object into all fields and methods that are annotated with the annotation
* defined by {@link #getPersistenceUnitConfigAnnotationClass()}
*
* @param testObject The test object, not null
*/
public void injectOrmPersistenceUnitIntoTestObject(Object testObject) {
Set fields = getFieldsAnnotatedWith(testObject.getClass(), getPersistenceUnitConfigAnnotationClass());
Set methods = getMethodsAnnotatedWith(testObject.getClass(), getPersistenceUnitConfigAnnotationClass());
// filter out methods without entity manager factory argument
Iterator iterator = methods.iterator();
while (iterator.hasNext()) {
Class>[] parameterTypes = iterator.next().getParameterTypes();
if (parameterTypes.length == 0 || !getPersistenceUnitClass().isAssignableFrom(parameterTypes[0])) {
iterator.remove();
}
}
if (fields.isEmpty() && methods.isEmpty()) {
// Jump out to make sure that we don't try to instantiate the EntityManagerFactory
return;
}
ORM_PERSISTENCE_UNIT persistenceUnit = getPersistenceUnit(testObject);
setFieldAndSetterValue(testObject, fields, methods, persistenceUnit);
}
/**
* Creates an instance of {@link org.unitils.orm.common.spring.OrmSpringSupport}, that
* implements the dependency to the {@link org.unitils.spring.SpringModule}. If the
* {@link org.unitils.spring.SpringModule} is not active, or if a dependency of
* {@link org.unitils.orm.common.spring.OrmSpringSupport} could not be found in the classpath,
* the instance is not loaded.
*/
protected void initOrmSpringSupport() {
if (!isSpringModuleEnabled()) {
return;
}
ormSpringSupport = createInstanceOfType(getOrmSpringSupportImplClassName(), false);
}
/**
* Verifies whether the SpringModule is enabled. If not, this means that either the property unitils.modules doesn't
* include spring, unitils.module.spring.enabled = false, or that the module could not be loaded because spring is not
* in the classpath.
*
* @return true if the SpringModule is enabled, false otherwise
*/
protected boolean isSpringModuleEnabled() {
// We specify the fully qualified classname of the spring module as string, to avoid classloading issues
return Unitils.getInstance().getModulesRepository().isModuleEnabled("org.unitils.spring.SpringModule");
}
protected DatabaseModule getDatabaseModule() {
return Unitils.getInstance().getModulesRepository().getModuleOfType(DatabaseModule.class);
}
public String getDatabaseName(Object testObject, Method testMethod) {
Set fields = AnnotationUtils.getFieldLevelAnnotations(testObject.getClass(), JpaEntityManagerFactory.class);
Set methods = AnnotationUtils.getMethodLevelAnnotations(testObject.getClass(), JpaEntityManagerFactory.class);
if (fields.isEmpty() && methods.isEmpty()) {
// Jump out to make sure that we don't try to instantiate the EntityManagerFactory
return "";
}
if (!fields.isEmpty()) {
return fields.iterator().next().databaseName();
}
return methods.iterator().next().databaseName();
}
/**
* The {@link TestListener} for this module
*/
protected class OrmTestListener extends TestListener {
@Override
public void beforeTestSetUp(Object testObject, Method testMethod) {
injectOrmPersistenceUnitIntoTestObject(testObject);
}
}
}