/**
* **************************************************************************
*
* Contributor(s):
* C. Heazel (WiSC): Added Fortify adjudication changes
*
***************************************************************************
*/
package com.occamlab.te.web;
import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.XMLConstants; // Addition for Fortify modifications
import net.sf.saxon.expr.FirstItemExpression;
import org.apache.commons.io.FileUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
/**
* Creates the main Config File reading the tests under TE_BASE/scripts config
* files It Aggregates by organization and by standard. The name of the
* organization and standards needs to match to be able to aggregate the tests.
* For example, two tests using Organization/name = 'OGC', will appear both
* under the 'OGC' organization. IF no tests exist under TE_BASE/scripts , still
* creates a config file with two elements config/scripts.
*
* If a previous config file exists, it will get deleted.
*
*/
public class ConfigFileCreator {
private static Logger LOGR = Logger
.getLogger("com.occamlab.te.web.ConfigFileCreator");
private DocumentBuilder builder;
private Document docMain;
private Element config;
private Element scripts;
public ConfigFileCreator() {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory
.newInstance();
try {
// Fortify Mod: prevent external entity injection
documentBuilderFactory.setExpandEntityReferences(false);
builder = documentBuilderFactory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
}
/**
* Creates the main config file. IF <code>tebase</code> is not found it will
* throw a <code>TEBaseNotFoundException</code>.
*
* @param tebase
*/
public void create(String tebase) throws TEException {
File f = new File(tebase);
if (f.exists()) {
try {
process(tebase);
} catch (Exception e) {
e.printStackTrace();
}
} else {
throw new TEBaseNotFoundException(tebase);
}
}
/**
* Creates the main config file.
*
* @param tebase
*/
public void create(File tebase) throws TEException {
try {
create(tebase.toString() + File.separator);
} catch (Exception e) {
throw e;
}
}
private void deleteConfigFile(String tebase) {
File f = new File(tebase + "config.xml");
if (f.exists()) {
f.delete();
LOGR.info("Old onfig file removed " + f);
} else {
LOGR.info("Config file not removed, since there was no file at "
+ f);
}
}
/**
* Process the the tests under the TEBASE folder, and creates an integrated
* config.xml. If no tests are found, it stills create a basic config file
* with two elements configs/scripts.
*
* @param tebase
* - path to TEBASE. Expected to have under TEBASE/scripts
*/
private void process(String tebase) {
deleteConfigFile(tebase);
docMain = builder.newDocument();
config = docMain.createElement("config");
docMain.appendChild(config);
scripts = docMain.createElement("scripts");
config.appendChild(scripts);
String scriptsDir = tebase + "scripts";
LOGR.info("Scripts directory found at " + scriptsDir);
File[] testScriptsDir = new File(scriptsDir).listFiles();
if (testScriptsDir != null) {
// if no tests are found under scripts, listFiles will return null,
// if not iterated over the scripts directories
for (File dir : testScriptsDir) {
processDir(dir);
}
}
String mainconfig = tebase + "config.xml";
saveConfigFile(docMain, mainconfig);
}
public void processDir(File dir) {
if (dir.isDirectory() && !dir.getName().startsWith(".")) {
List<File> configFiles = getConfigFiles(dir);
for (Iterator iterator = configFiles.iterator(); iterator.hasNext();) {
File file = (File) iterator.next();
processTestConfigFile(file);
}
}
}
private void processTestConfigFile(File configFile) {
if (configFile != null) {
Document docTest = getDocument(configFile);
Node orgInTest = XMLUtils.getFirstNode(docTest,
"/organization/name[1]");
String org = orgInTest.getTextContent();
String xpath = "/config/scripts/organization/name[text()='" + org
+ "']";
Node orgInMainConfig = XMLUtils.getFirstNode(docMain, xpath);
// org doesn't exist
if (orgInMainConfig == null) {
// append to scripts
Node orgInTestImported = docMain.importNode(
orgInTest.getParentNode(), true);
scripts.appendChild(orgInTestImported);
} else {
Node standardInTest = XMLUtils.getFirstNode(docTest,
"/organization/standard[1]");
String standardInTestName = XMLUtils.getFirstNode(docTest,
"/organization/standard[1]/name").getTextContent();
// check if a standard with this name already exists in main
xpath = "/config/scripts/organization/standard/name[text()='"
+ standardInTestName + "']";
Node standardInMain = XMLUtils.getFirstNode(docMain, xpath);
if (standardInMain == null) {
// append to an existing organization
Node orgInMain = orgInMainConfig.getParentNode();
orgInMain.appendChild(docMain.importNode(standardInTest,
true));
} else {
// standard already exists in main config, so append to
// standard
Node versionInTest = XMLUtils.getFirstNode(docTest,
"/organization/standard/version[1]");
standardInMain.getParentNode().appendChild(
docMain.importNode(versionInTest, true));
}
}
LOGR.config("Added " + configFile.getAbsolutePath()
+ " to config file");
} else {
LOGR.config("No config file was found in dir "
+ configFile.getAbsolutePath()
+ ". It was not registered in the main config file.");
}
}
public void saveConfigFile(Document docMain, String mainconfig) {
try {
TransformerFactory transformerFactory = TransformerFactory
.newInstance();
// Fortify Mod: prevent external entity injection
transformerFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
DOMSource source = new DOMSource(docMain);
StreamResult result = new StreamResult(new FileOutputStream(
mainconfig));
LOGR.info("SUCCESSFULLY created config.xml at " + mainconfig);
transformer.transform(source, result);
} catch (Exception e) {
LOGR.warning("The main config file was not created at "
+ mainconfig);
e.printStackTrace();
}
}
public Document getDocument(File xml) {
try {
Document doc = builder.parse(xml);
return doc;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* Returns the all config file found under a directory
*
* @param dir
* @return A list of files found. Length = 0 if not found files.
*/
private List<File> getConfigFiles(File dir) {
String[] extensions = { "xml" };
List<File> configFiles = new ArrayList<File>();
Collection<File> files = FileUtils.listFiles(dir, extensions, true);
for (Iterator<File> iterator = files.iterator(); iterator.hasNext();) {
File file = (File) iterator.next();
if (file.getName().equals("config.xml")) {
configFiles.add(file);
}
}
return configFiles;
}
}