/**
* This Source Code Form is subject to the terms of the Mozilla Public License,
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
* obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under
* the terms of the Healthcare Disclaimer located at http://openmrs.org/license.
*
* Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS
* graphic logo is a trademark of OpenMRS Inc.
*/
package org.openmrs.test;
import java.net.URL;
import java.util.Enumeration;
import java.util.Properties;
import org.apache.commons.lang.StringUtils;
import org.junit.Assert;
import org.openmrs.api.context.Context;
import org.openmrs.api.db.SerializedObjectDAOTest;
import org.openmrs.module.ModuleConstants;
import org.openmrs.module.ModuleFactory;
import org.openmrs.module.ModuleInteroperabilityTest;
import org.openmrs.module.ModuleUtil;
import org.openmrs.util.OpenmrsClassLoader;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.io.UrlResource;
import org.springframework.test.context.TestContext;
import org.springframework.test.context.support.AbstractTestExecutionListener;
/**
* To use this annotation, add the @StartModule( { "/path/to/your/module.omod" } ) annotation to the
* test class
*
* @see SerializedObjectDAOTest
* @see ModuleInteroperabilityTest
* @see BaseContextSensitiveTest
*/
public class StartModuleExecutionListener extends AbstractTestExecutionListener {
// stores the last class that restarted the module system because we only
// want it restarted once per class, not once per method
private static String lastClassRun = "";
/**
* called before @BeforeTransaction methods
*
* @see org.springframework.test.context.support.AbstractTestExecutionListener#prepareTestInstance(org.springframework.test.context.TestContext)
*/
@Override
public void prepareTestInstance(TestContext testContext) throws Exception {
StartModule startModuleAnnotation = testContext.getTestClass().getAnnotation(StartModule.class);
// if the developer listed some modules with the @StartModule annotation on the class
if (startModuleAnnotation != null) {
if (!lastClassRun.equals(testContext.getTestClass().getSimpleName())) {
// mark this with our class so that the services are only restarted once
lastClassRun = testContext.getTestClass().getSimpleName();
if (!Context.isSessionOpen())
Context.openSession();
ModuleUtil.shutdown();
// load the omods that the dev defined for this class
String modulesToLoad = StringUtils.join(startModuleAnnotation.value(), " ");
Properties props = BaseContextSensitiveTest.runtimeProperties;
props.setProperty(ModuleConstants.RUNTIMEPROPERTY_MODULE_LIST_TO_LOAD, modulesToLoad);
try {
ModuleUtil.startup(props);
}
catch (Exception e) {
System.out.println("Error while starting modules: ");
e.printStackTrace(System.out);
throw e;
}
Assert.assertTrue("Some of the modules did not start successfully for "
+ testContext.getTestClass().getSimpleName() + ". Only " + ModuleFactory.getStartedModules().size()
+ " modules started instead of " + startModuleAnnotation.value().length, startModuleAnnotation
.value().length <= ModuleFactory.getStartedModules().size());
/*
* Refresh spring so the Services are recreated (aka serializer gets put into the SerializationService)
* To do this, wrap the applicationContext from the testContext into a GenericApplicationContext, allowing
* loading beans from moduleApplicationContext into it and then calling ctx.refresh()
* This approach ensures that the application context remains consistent
*/
GenericApplicationContext ctx = new GenericApplicationContext(testContext.getApplicationContext());
XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(ctx);
Enumeration<URL> list = OpenmrsClassLoader.getInstance().getResources("moduleApplicationContext.xml");
while (list.hasMoreElements()) {
xmlReader.loadBeanDefinitions(new UrlResource(list.nextElement()));
}
//ensure that when refreshing, we use the openmrs class loader for the started modules.
boolean useSystemClassLoader = Context.isUseSystemClassLoader();
Context.setUseSystemClassLoader(false);
try {
ctx.refresh();
}
finally {
Context.setUseSystemClassLoader(useSystemClassLoader);
}
// session is closed by the test framework
//Context.closeSession();
}
}
}
@Override
public void afterTestClass(TestContext testContext) throws Exception {
StartModule startModuleAnnotation = testContext.getTestClass().getAnnotation(StartModule.class);
if (startModuleAnnotation != null) {
if (!Context.isSessionOpen()) {
Context.openSession();
}
ModuleUtil.shutdown();
Context.closeSession();
}
}
}