/*
* The Kuali Financial System, a comprehensive financial management system for higher education.
*
* Copyright 2005-2014 The Kuali Foundation
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.kuali.kfs.sys.context;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FilenameFilter;
import java.io.PrintStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.kuali.kfs.sys.ConfigureContext;
import org.kuali.kfs.sys.service.UniversityDateService;
import org.kuali.kfs.sys.suite.AnnotationTestSuite;
import org.kuali.kfs.sys.suite.PreCommitSuite;
import org.kuali.rice.coreservice.api.parameter.Parameter;
import org.kuali.rice.coreservice.framework.parameter.ParameterService;
import org.kuali.rice.krad.service.KRADServiceLocator;
import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
import org.springframework.aop.framework.ProxyFactory;
/**
* This class provides utility methods for use during manual testing.
*/
@AnnotationTestSuite(PreCommitSuite.class)
public class TestUtils {
private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(TestUtils.class);
private static Integer fiscalYearForTesting;
private static String periodCodeForTesting;
private static final String PLACEHOLDER_FILENAME = "placeholder.txt";
private static ParameterService parameterService;
public static ParameterService getParameterService() {
if ( parameterService == null ) {
parameterService = SpringContext.getBean(ParameterService.class);
}
return parameterService;
}
/**
* This sets a given system parameter and clears the method cache for retrieving the parameter.
*/
public static void setSystemParameter(Class componentClass, String parameterName, String parameterText) {
// check that we are in a test that is set to roll-back the transaction
Exception ex = new Exception();
ex.fillInStackTrace();
Boolean willCommit = null;
// loop over the stack trace
for ( StackTraceElement ste : ex.getStackTrace() ) {
try {
Class clazz = Class.forName( ste.getClassName() );
// for efficiency, only check classes that extend from KualiTestBase
if ( KualiTestBase.class.isAssignableFrom(clazz) ) {
//System.err.println( "Checking Method: " + ste.toString() );
// check the class-level annotation to set the default for test methods in that class
ConfigureContext a = (ConfigureContext)clazz.getAnnotation(ConfigureContext.class);
if ( a != null ) {
willCommit = a.shouldCommitTransactions();
}
// now, check the method-level annotation
try {
Method m = clazz.getMethod(ste.getMethodName(), (Class[])null);
// if the method-level annotation is present, it overrides the class-level annotation
a = (ConfigureContext)m.getAnnotation(ConfigureContext.class);
if ( a != null ) {
willCommit = a.shouldCommitTransactions();
}
} catch ( NoSuchMethodException e ) {
// do nothing
}
}
} catch ( Exception e ) {
LOG.error( "Error checking stack trace element: " + ste.toString(), e );
}
}
if ( willCommit == null || willCommit ) {
throw new RuntimeException( "Attempt to set system parameter in unit test set to commit database changes.");
}
Parameter parameter = getParameterService().getParameter(componentClass, parameterName);
Parameter.Builder newParm = Parameter.Builder.create(parameter);
newParm.setValue(parameterText);
getParameterService().updateParameter(newParm.build());
}
/**
* Returns an invoked instance for the serviceName passed. This uses SpringContext.getService but doesn't return the proxy. Should only
* be used for unit testing purposes
* @param serviceName service to return
* @throws Exception
*/
public static Object getUnproxiedService(String serviceName) throws Exception {
Object service = SpringContext.getService(serviceName);
if ( service == null ) {
return null;
}
try {
InvocationHandler invocationHandler = Proxy.getInvocationHandler(service);
Field privateAdvisedField = invocationHandler.getClass().getDeclaredField("advised");
privateAdvisedField.setAccessible(true);
ProxyFactory proxyFactory = (ProxyFactory) privateAdvisedField.get(invocationHandler);
return proxyFactory.getTargetSource().getTarget();
} catch ( IllegalArgumentException ex ) {
return service;
} catch ( NoSuchFieldException ex ) {
LOG.error( "Problem obtaining advised object: " + ex.getMessage() );
LOG.error( "Invocation Handler: " + Proxy.getInvocationHandler(service) );
return service;
}
}
/**
* Writes an array to a file. Useful for GL / LD poster file handling.
* @param filePath file and path to write
* @param inputTransactions data to write to pathname
* @throws IllegalArgumentException if file already exists
*/
public static void writeFile(String filePath, String[] inputTransactions) {
File file = new File(filePath);
if (file.exists()) {
if(!file.delete()) {
throw new RuntimeException("Attempt to overwrite " + file.getName() + " failed.");
}
}
PrintStream outputFileStream = null;
try {
outputFileStream = new PrintStream(file);
}
catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
for (String line: inputTransactions){
outputFileStream.printf("%s\n", line);
}
outputFileStream.close();
}
/**
* Deletes all files from a directory except PLACEHOLDER_FILENAME.
* @param path of the directory to empty
*/
public static void deleteFilesInDirectory(String pathname) {
FilenameFilter filenameFilter = new FilenameFilter() {
public boolean accept(File dir, String name) {
return (!name.equals(PLACEHOLDER_FILENAME));
}
};
File directory = new File(pathname);
File[] directoryListing = directory.listFiles(filenameFilter);
if (directoryListing == null) {
throw new IllegalArgumentException("Directory doesn't exist: " + pathname);
} else {
for (int i = 0; i < directoryListing.length; i++) {
File file = directoryListing[i];
if(!file.delete()) {
throw new RuntimeException("Delete of " + file.getName() + " failed.");
}
}
}
}
/**
* Returns a fiscal year for testing. If the fiscalYearForTesting property is not null, it returns that;
* otherwise, it runs the current fiscal year
* @return a fiscal year suitable for testing purposes
*/
public static Integer getFiscalYearForTesting() {
if (fiscalYearForTesting == null) {
fiscalYearForTesting = SpringContext.getBean(UniversityDateService.class).getCurrentFiscalYear();
}
return fiscalYearForTesting;
}
/**
* Returns a period code for testing. If the periodCodeForTesting property is not null, it returns that;
* otherwise, it runs the current period code
* @return a period code suitable for testing purposes
*/
public static String getPeriodCodeForTesting() {
if (periodCodeForTesting == null) {
periodCodeForTesting = SpringContext.getBean(UniversityDateService.class).getCurrentUniversityDate().getUniversityFiscalAccountingPeriod();
}
return periodCodeForTesting;
}
}