/*
* Copyright 2005-2010 Ignis Software Tools Ltd. All rights reserved.
*/
package jsystem.upgrade;
import java.io.File;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.text.SimpleDateFormat;
import java.util.Properties;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;
import jsystem.framework.FrameworkOptions;
import jsystem.framework.JSystemProperties;
import jsystem.framework.scenario.RunnerTest;
import jsystem.framework.scenario.Scenario;
import jsystem.framework.scenario.ScenariosManager;
import jsystem.runner.ErrorLevel;
import jsystem.treeui.WaitDialog;
import jsystem.treeui.error.ErrorPanel;
import jsystem.utils.DateUtils;
import jsystem.utils.FileUtils;
import jsystem.utils.StringUtils;
import jsystem.utils.XmlUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
/**
* As from version 4.8 the format of scenario files was changed. The new format
* is of standart ANT file format and we uses the ANT engien to execute the
* scenario. The entry point will be <code>processOldFormatScenarios</code>
* method.
*
* @author guy.arieli
*
*/
public class ScenarioConversion {
private static Logger log = Logger.getLogger(ScenarioConversion.class.getName());
private static ScenarioConversion sc = null;
private static SimpleDateFormat dateFormat = new SimpleDateFormat("MM_dd_hh_mm_ss");
public static ScenarioConversion getInstance() {
if (sc == null) {
sc = new ScenarioConversion();
}
return sc;
}
static private DocumentBuilder db;
private ScenarioConversion() {
// private constractor (use the singleton)
try {
db = XmlUtils.getDocumentBuilder();
} catch (ParserConfigurationException e) {
log.log(Level.WARNING, "Fail to init the document builder", e);
}
}
/**
* Collect all the scenario in the old format
*
* @return a <code>Vector</code> of the old scenario
*/
public Vector<File> collectOldScenarios() {
Vector<File> allScenarios = new Vector<File>();
String testsClassesFolderName = JSystemProperties.getInstance().getPreference(
FrameworkOptions.TESTS_CLASS_FOLDER);
if (testsClassesFolderName == null) {
return allScenarios;
}
FileUtils.collectAllFiles(new File(testsClassesFolderName), new FilenameFilter() {
public boolean accept(File dir, String name) {
if (!name.toLowerCase().endsWith(".xml")) {
return false;
}
Document doc;
try {
doc = db.parse(new File(dir, name));
} catch (Exception e) {
return false;
}
/*
* If the root tag is <tests> ...
*/
return ((Element) doc.getDocumentElement()).getTagName().equals("tests");
}
}, allScenarios);
return allScenarios;
}
/**
* Convert a single scenario file.
*
* @param scenarioFile
* the scenario file to convert.
* @return the converted scenario.
* @throws Exception
* the scenario convertion failed.
*/
private Scenario convertScenario(File scenarioFile) throws Exception {
log.info("Converting " + scenarioFile);
File classesDirectory = new File(JSystemProperties.getInstance().getPreference(
FrameworkOptions.TESTS_CLASS_FOLDER));
String scenarioName = scenarioFile.getAbsolutePath().substring(classesDirectory.getAbsolutePath().length() + 1,
scenarioFile.getAbsolutePath().length() - 4);
FileInputStream fis = new FileInputStream(scenarioFile);
Document doc = db.parse(fis);
fis.close();
/*
* If scenario is already converted will return it as is.
*/
if(((Element) doc.getDocumentElement()).getTagName().equals("project")){
return ScenariosManager.getInstance().getScenario(scenarioName);
}
NodeList children = doc.getDocumentElement().getChildNodes();
Scenario scenario = ScenariosManager.getInstance().getScenario(scenarioName);
ScenariosManager.getInstance().setCurrentScenario(scenario);
if (scenario.getTests().size() > 0) {
return scenario;
}
for (int i = 0; i < children.getLength(); i++) {
if (children.item(i) instanceof Element) {
Element el = (Element) children.item(i);
if (el.getTagName().equals("scenario")) {
String sName = el.getAttribute("name");
String d = el.getAttribute("User-Doc");
File scenarioToConvertFile = new File(classesDirectory.getAbsolutePath() + File.separator + sName
+ ".xml");
/*
* If the scenario doesn't exit will continue
*/
if(!scenarioToConvertFile.exists()){
log.log(Level.WARNING,"Scenario file: " + sName + " couldn't be found and will be ignored");
continue;
}
Scenario s = convertScenario(scenarioToConvertFile);
if (d != null){
s.setDocumentation(d);
}
scenario.addTest(s);
} else {
// at this point the test has no actual test
// associated
RunnerTest test = fromElement((Element) children.item(i));
test.setParent(scenario);
test.setDisable(Boolean.valueOf((String) test.getProperties().get("disable")).booleanValue());
// fix the old scenario file format problem
if (test.getClassName().indexOf(';') >= 0 || test.getMethodName().indexOf(';') >= 0) {
continue;
}
scenario.addTest(test);
}
}
}
return scenario;
}
/**
* constructs a RunnerTest from and Element got from the scenario xml file
* initiates the test's properties from the element. uses the Test to get
* the method (includes searching in super classes)
*
* @param e
* the element from the xml file
* @param test
* the new created RunnerTest Test
* @return a RunnerTest instance
* @throws Exception
*/
private static RunnerTest fromElement(Element e) throws Exception {
String className = e.getAttribute("class");
String methodName = ((Text) e.getFirstChild()).getData();
if (methodName == null) {
return null;
}
RunnerTest rTest = new RunnerTest(className, methodName);
NamedNodeMap attributes = e.getAttributes();
Properties p = new Properties();
String name;
for (int i = 0; i < attributes.getLength(); i++) {
Node att = attributes.item(i);
String attName = att.getNodeName();
if (attName.equals("User-Doc")) {
rTest.setDocumentation(att.getNodeValue());
continue;
}
if (attName.equals("comment")) {
rTest.setTestComment(att.getNodeValue());
continue;
}
if (attName.equals("disable")) {
if("true".equals(att.getNodeValue())){
rTest.setDisable(true);
}
continue;
}
if (!attName.equals("class")) {
name = attName;
p.put(name, att.getNodeValue());
}
}
rTest.setProperties(p);
return rTest;
}
/**
* The entry point to the class. Execute all the conversion process
*
*/
public void processOldFormatScenarios() {
String convertString = JSystemProperties.getInstance().getPreference(FrameworkOptions.DISABLE_OLD_SCENARIO_CONVERT);
if (!StringUtils.isEmpty(convertString) && convertString.startsWith("true")) {
return;
}
if (!StringUtils.isEmpty(convertString) && convertString.startsWith("never")) {
return;
}
try {
Vector<File> oldScenarios = ScenarioConversion.getInstance().collectOldScenarios();
if (oldScenarios == null || oldScenarios.size() == 0) {
JSystemProperties.getInstance().setPreference(FrameworkOptions.DISABLE_OLD_SCENARIO_CONVERT, "true");
return;
}
String classesFolder = JSystemProperties.getInstance().getPreference(FrameworkOptions.TESTS_CLASS_FOLDER);
String classesFolderPatent = new File(classesFolder).getParent();
String backupName = getBackupFileName();
File backupFile = new File(classesFolderPatent,backupName);
if (JOptionPane.OK_OPTION != JOptionPane.showConfirmDialog(null,
"An old scenario format was found, JSystem can automatically\n"
+ "convert them to the new format. A zip file with the old files\n"
+ "will be created. The new scenarios are formated as\n" + "ANT file. Continue?",
"Scenario format change", JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE)) {
return;
}
FileUtils.zipDirectory(
classesFolder,
".xml", backupFile.getAbsolutePath());
ErrorPanel.showErrorDialog("Old scenarios have been backed up to: " +backupFile.getName() , backupFile.getAbsolutePath(), ErrorLevel.Info);
WaitDialog.launchWaitDialog("Convert scenarios", null);
for (File scenarioFile : oldScenarios) {
try {
ScenarioConversion.getInstance().convertScenario(scenarioFile);
} catch (Exception ce) {
WaitDialog.endWaitDialog();
ErrorPanel.showErrorDialog("Scenario conversion fail", "Scenario file: " + scenarioFile.getName()
+ "\n" + StringUtils.getStackTrace(ce), ErrorLevel.Warning);
WaitDialog.launchWaitDialog("Convert scenarios", null);
}
}
WaitDialog.endWaitDialog();
} catch (Exception e) {
log.log(Level.WARNING, "Old scenario convertion fail", e);
return;
}
ScenariosManager.init();
}
private String getBackupFileName() throws Exception {
String currentDate =
DateUtils.getDate(System.currentTimeMillis(), dateFormat);
return "scenariosBackup_"+currentDate+".zip";
}
public void resetScenarioConvertorFlag() {
String convertString = JSystemProperties.getInstance().getPreference(FrameworkOptions.DISABLE_OLD_SCENARIO_CONVERT);
if (!StringUtils.isEmpty(convertString) && convertString.startsWith("never")){
return;
}
JSystemProperties.getInstance().setPreference(FrameworkOptions.DISABLE_OLD_SCENARIO_CONVERT, "false");
}
}