package net.raymanoz.migrate;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import net.raymanoz.config.ConditionDecoder;
import net.raymanoz.config.Configuration;
import net.raymanoz.config.ScriptStatus;
import net.raymanoz.config.VariableEvaluater;
import net.raymanoz.config.VariableEvaluaterImpl;
import net.raymanoz.io.File;
import net.raymanoz.ui.UserInteractionStrategy;
import net.raymanoz.util.FileUtil;
import net.raymanoz.util.FileUtilImpl;
import net.raymanoz.util.ScriptExecuterCommandLineParser;
public class ScriptImpl implements Script {
private static final Log LOG = LogFactory.getLog(ScriptImpl.class);
private File file;
private ScriptAssembler assembler;
private String conditionStatus = "Not Checked";
public ScriptImpl(File file, ScriptAssembler assembler) {
if (!isScriptFile(file)) {
throw new IllegalArgumentException(file.getName()
+ " is not a valid uMigrate file");
}
this.file = file;
this.assembler = assembler;
}
static public boolean isScriptFile(File file) {
return getMatcher(file).find();
}
static private Matcher getMatcher(File file) {
return Pattern.compile("^[0123456789]+").matcher(file.getName());
}
public long getPatch() {
Matcher matcher = getMatcher(file);
matcher.find();
return new Long(matcher.group(0));
}
public int compareTo(Script o) {
Script that = (Script) o;
long thisNumber = this.getPatch();
long thatNumber = that.getPatch();
if (thisNumber < thatNumber) {
return -1;
} else if (thisNumber == thatNumber) {
return 0;
} else {
return 1;
}
}
public ScriptStatus execute(UserInteractionStrategy userInteractionStrategy) {
try {
ConditionDecoder decoder = assembler.getConditionDecoder();
decoder.setScriptText(file);
conditionStatus = decoder.conditionStatuses();
switch (decoder.ShouldRunScript()){
case HALT: return ScriptStatus.HALTED;
case RUN_SCRIPT: break;
case SKIP_SCRIPT: return ScriptStatus.SKIPPED;
default: throw new RuntimeException("Unknown Script Status");
}
File executeFile = createExecuteFile(assembler.getConfiguration());
Process process = executeScript(executeFile, userInteractionStrategy);
try {
process.waitFor();
} catch (InterruptedException e) {
return ScriptStatus.ERRORED;
}
if (process.exitValue() == 0) {
return ScriptStatus.COMPLETED;
}
return ScriptStatus.ERRORED;
}
catch(Exception e){
LOG.error(getFileName(), e);
Throwable rc = e;
while (rc.getCause() != null) rc = rc.getCause();
conditionStatus = rc.toString();
return ScriptStatus.ERRORED;
}
}
protected void assignStandardOutputs(Process process, UserInteractionStrategy userInteractionStrategy) {
assembler.newInputStreamPrinter(process.getInputStream(), System.out, userInteractionStrategy).print();
assembler.newInputStreamPrinter(process.getErrorStream(), System.err, userInteractionStrategy).print();
}
protected Process executeScript(File executeFile, UserInteractionStrategy userInteractionStrategy) {
ScriptExecuterCommandLineParser parser = assembler.getScriptExecuterCommandLineParser();
ScriptProcessBuilder builder = assembler.newProcessBuilder();
builder.command(parser.processBuilderArgs(executeFile));
Process process = builder.start();
assignStandardOutputs(process, userInteractionStrategy);
return process;
}
protected File createExecuteFile(Configuration configuration) {
File executeDirectory = configuration.getExecuteDirectory();
File executeFile = assembler.newFile(executeDirectory, file.getName());
FileUtil fileUtil = assembler.getFileUtil();
fileUtil.copyFile(file, executeFile, assembler.getProperties());
return executeFile;
}
public String getFileName() {
return file.getName();
}
public long getDBVersion() {
return file.getDBVersion();
}
public String condtionStatus() {
return conditionStatus;
}
String getScriptText() {
try {
InputStream out = new FileInputStream(file.getJavaFile());
try{
return FileUtilImpl.readStreamText(out);
}
finally {
out.close();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public Set<String> variablesRequiringDialog() {
final VariableEvaluater variableEvaluater = new VariableEvaluaterImpl(assembler.getProperties());
return variableEvaluater.findVariablesRequiringDialog(getScriptText());
}
@Override
public String description() {
return "Script [ DBVersion: " + getDBVersion() + ", Patch: " + getPatch() + ", FileName: '" + getFileName() + "' ]";
}
}