package org.unitils.dbmaintainer.script.impl;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.unitils.dbmaintainer.locator.ClassPathScriptLocator;
import org.unitils.dbmaintainer.locator.resourcepickingstrategie.ResourcePickingStrategie;
import org.unitils.dbmaintainer.locator.resourcepickingstrategie.impl.UniqueMostRecentPickingStrategie;
import org.unitils.dbmaintainer.script.Script;
import org.unitils.util.PropertyUtils;
/**
* Implementation of {@link ScriptSource} that reads script files from the classpath.
* <p/>
* <p>
* Wildcards in naming are allowed. When looking through the classpath it will use the {@link PathMatchingResourcePatternResolver} provided
* by Spring.
* </p>
* When finding multiple files that have the same name the system will take te most recent one. Script files should be located in the
* package configured by {@link #PROPKEY_SCRIPT_LOCATIONS}. Valid script files start with a version number followed by an underscore, and
* end with the extension configured by {@link #PROPKEY_SCRIPT_EXTENSIONS}.
*
* @author Thomas De Rycke
* @author Jef Verelst
*
* @since 1.0.2
*
*/
public class ResourceScriptSource extends DefaultScriptSource {
private static final Log LOGGER = LogFactory.getLog(ResourceScriptSource.class);
/** */
public ResourceScriptSource() {
}
/**
*
* @see org.unitils.dbmaintainer.script.impl.DefaultScriptSource#loadAllScripts()
*/
@Override
protected List<Script> loadAllScripts(String dialect, String databaseName, boolean defaultDatabase) {
List<String> scriptLocations = PropertyUtils.getStringList("dbMaintainer.script.locations", configuration);
//String dbDialect = PropertyUtils.getString(PROPKEY_DATABASE_DIALECT, configuration);
if(dialect != null) {
List<String> dbSpecificLocations = PropertyUtils.getStringList("dbMaintainer.script.locations." + dialect, configuration);
scriptLocations.addAll(dbSpecificLocations);
}
List<String> scriptIgnoredLocations = PropertyUtils.getStringList("dbMaintainer.script.locations.ignore", configuration);
List<String> ignoredSubLocations = new ArrayList<String>();
for (String locationIgnorded : scriptIgnoredLocations) {
for (String scriptLocation : scriptLocations) {
if (locationIgnorded.startsWith(scriptLocation)) {
String sublocation = locationIgnorded.replace(scriptLocation, "");
if (sublocation.startsWith("/")) {
sublocation = sublocation.substring(1);
}
ignoredSubLocations.add(sublocation);
}
}
}
LOGGER.debug("Ignorded sublocations for script search: " + ArrayUtils.toString(ignoredSubLocations.toArray()));
List<Script> scripts = new ArrayList<Script>();
String scriptLocation;
for (Iterator<String> i = scriptLocations.iterator(); i.hasNext(); getScriptsAt(scripts, scriptLocation, "", databaseName, defaultDatabase)) {
scriptLocation = i.next();
}
List<Script> scriptsToRemove = new ArrayList<Script>();
for (Script script : scripts) {
for (String ignoredSublocation : ignoredSubLocations) {
if (script.getFileName().startsWith(ignoredSublocation)) {
LOGGER.debug("Removing script '" + script.getFileName() + "' because in ignored sub-location " + ignoredSublocation);
scriptsToRemove.add(script);
}
}
}
scripts.removeAll(scriptsToRemove);
LOGGER.debug("Scripts found: " + scripts.size());
return scripts;
}
/**
*
* @see org.unitils.dbmaintainer.script.impl.DefaultScriptSource#getScriptsAt(java.util.List, java.lang.String, java.lang.String)
*/
@Override
protected void getScriptsAt(List<Script> scripts, String scriptRoot, String relativeLocation, String databaseName, boolean defaultDatabase) {
if(!scriptRoot.endsWith("/")) {
// for one reason or another, it doesn't work when there is no / at the end
scriptRoot += "/";
}
String location = scriptRoot;
LOGGER.debug("Script location: " + location);
ClassPathScriptLocator classPathScriptLocator = new ClassPathScriptLocator();
classPathScriptLocator.loadScripts(scripts, scriptRoot, getResourcePickingStrategie(), getScriptExtensions(), databaseName, defaultDatabase, configuration);
List<Script> tempScripts = new ArrayList<Script>();
for (Script script : scripts) {
if (checkIfScriptContainsCorrectDatabaseName(script.getFileName(), databaseName, defaultDatabase) && containsOneOfQualifiers(script.getFileName())) {
tempScripts.add(script);
}
}
scripts = tempScripts;
}
/**
* use unitil propertie instead of hardcoding
*
* @return
*/
protected ResourcePickingStrategie getResourcePickingStrategie() {
return new UniqueMostRecentPickingStrategie();
}
}