diff --git a/pom.xml b/pom.xml index be93181..27d2014 100644 --- a/pom.xml +++ b/pom.xml @@ -12,6 +12,7 @@ UTF-8 + src/main/java @@ -40,6 +41,7 @@ org.apache.maven.plugins maven-dependency-plugin + copy-dependencies prepare-package @@ -53,11 +55,61 @@ true + + + + unpack-ruleset + generate-resources + + unpack + + + + + de.darmstadt.tu.crossing + JavaCryptographicArchitecture + 3.1.1 + zip + ruleset + true + ${project.build.directory}/generated-resources + + + + + + + + + org.apache.maven.plugins + maven-resources-plugin + 3.2.0 + + + copy-ruleset-to-resources + generate-resources + + copy-resources + + + src/main/resources/CrySLRules + + + ${project.build.directory}/generated-resources/JavaCryptographicArchitecture + + **/*.crysl + + + + + + + @@ -72,7 +124,6 @@ 3.1.1 - junit junit diff --git a/src/main/java/de/upb/docgen/DocSettings.java b/src/main/java/de/upb/docgen/DocSettings.java index 959484f..f2bdf79 100644 --- a/src/main/java/de/upb/docgen/DocSettings.java +++ b/src/main/java/de/upb/docgen/DocSettings.java @@ -118,7 +118,7 @@ public void parseSettingsFromCLI(String[] settings) { case "--rulesdir": setRulesetPathDir(settings[i + 1]); i++; - mandatorySettings++; + // mandatorySettings++; break; case "--reportpath": setReportDirectory(settings[i + 1]); @@ -128,12 +128,12 @@ public void parseSettingsFromCLI(String[] settings) { case "--ftltemplatespath": setFTLTemplatesPath(settings[i + 1]); i++; - mandatorySettings++; + // mandatorySettings++; break; case "--langtemplatespath": setLangTemplatesPath(settings[i + 1]); i++; - mandatorySettings++; + // mandatorySettings++; break; case "--booleana": setBooleanA(false); @@ -161,7 +161,7 @@ public void parseSettingsFromCLI(String[] settings) { System.exit(255); } } - if (mandatorySettings != 4) { + if (mandatorySettings != 1) { showErrorMessage(); System.exit(255); } diff --git a/src/main/java/de/upb/docgen/DocumentGeneratorMain.java b/src/main/java/de/upb/docgen/DocumentGeneratorMain.java index 8323e26..1fe12b6 100644 --- a/src/main/java/de/upb/docgen/DocumentGeneratorMain.java +++ b/src/main/java/de/upb/docgen/DocumentGeneratorMain.java @@ -1,20 +1,24 @@ package de.upb.docgen; -import java.io.*; -import java.util.*; - import crypto.exceptions.CryptoAnalysisException; import crypto.rules.CrySLPredicate; import crypto.rules.CrySLRule; import crypto.rules.CrySLRuleReader; +import de.upb.docgen.crysl.CrySLReader; import de.upb.docgen.utils.PredicateTreeGenerator; import de.upb.docgen.utils.TreeNode; import de.upb.docgen.utils.Utils; import de.upb.docgen.writer.FreeMarkerWriter; -import freemarker.template.*; +import freemarker.template.Configuration; +import freemarker.template.TemplateException; +import freemarker.template.Version; import org.apache.commons.io.FileUtils; -import javax.print.Doc; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; +import java.util.*; /** * @author Ritika Singh @@ -33,7 +37,14 @@ public static void main(String[] args) throws IOException, TemplateException, Cr // read CryslRules from absolutePath provided by the user System.out.println("Reading CrySL Rules"); - List rules = ruleReader.readFromDirectory(new File(docSettings.getRulesetPathDir())); + + + List rules = null; + if (docSettings.getRulesetPathDir() != null) { + rules = ruleReader.readFromDirectory(new File(docSettings.getRulesetPathDir())); + } else { + rules = CrySLReader.readRulesFromJar(); + } @@ -146,12 +157,44 @@ public static void main(String[] args) throws IOException, TemplateException, Cr // specifify this flag to distribute the documentation System.out.println("CogniCryptDOC generated to: " + DocSettings.getInstance().getReportDirectory()); if (!docSettings.isBooleanF()) { - File source = new File(docSettings.getRulesetPathDir()); + boolean readFromJar = false; + File source = null; + if (DocSettings.getInstance().getRulesetPathDir() != null) { + source = new File(docSettings.getRulesetPathDir()); + } else { + readFromJar = true; + source = new File("tempRulesDir"); + if (!source.exists()) { + source.mkdir(); + } + + // Read each rule and save it in the temporary directory + for (CrySLRule rule : rules) { + File ruleFile = CrySLReader.readRuleFromJarFile(rule.getClassName().substring(rule.getClassName().lastIndexOf(".") + 1)); + if (ruleFile != null && ruleFile.exists()) { + try { + // Copy each rule file into the temporary directory + Files.copy(ruleFile.toPath(), new File(source, ruleFile.getName()).toPath(), StandardCopyOption.REPLACE_EXISTING); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } File dest = new File(docSettings.getReportDirectory() + File.separator + "rules"); try { FileUtils.copyDirectory(source, dest); } catch (IOException e) { e.printStackTrace(); + } finally { + // Cleanup the temporary directory + if (readFromJar) { + try { + FileUtils.deleteDirectory(source); + } catch (IOException e) { + e.printStackTrace(); + } + } } } diff --git a/src/main/java/de/upb/docgen/Order.java b/src/main/java/de/upb/docgen/Order.java index 8c6378c..0dfa4a3 100644 --- a/src/main/java/de/upb/docgen/Order.java +++ b/src/main/java/de/upb/docgen/Order.java @@ -17,6 +17,8 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; +import crypto.exceptions.CryptoAnalysisException; +import de.upb.docgen.crysl.CrySLReader; import org.apache.commons.lang3.StringUtils; import crypto.rules.CrySLRule; @@ -66,7 +68,19 @@ private static Map getSymValues() throws IOException { Properties properties = new Properties(); try { - File fileone = new File(DocSettings.getInstance().getLangTemplatesPath() + "/symbol.properties"); + File fileone = null; + + if (DocSettings.getInstance().getRulesetPathDir() != null) { + fileone = new File(DocSettings.getInstance().getLangTemplatesPath() + "/symbol.properties"); + + } else { + fileone = CrySLReader.readSymbolPropertiesFromJar(); + } + + + + + FileInputStream fileInput = new FileInputStream(fileone); properties.load(fileInput); fileInput.close(); @@ -314,10 +328,24 @@ private static void getProcessedMap(List eventList) { } - public List runOrder(CrySLRule file) throws IOException { - String filePath = DocSettings.getInstance().getRulesetPathDir(); - filePath += File.separator + file.getClassName().substring(file.getClassName().lastIndexOf(".") + 1) + ".crysl"; - Map> fileContent = readCryslFile(filePath); + public List runOrder(CrySLRule file) throws IOException, CryptoAnalysisException { + + + File rule = null; + Map> fileContent = null; + + if (DocSettings.getInstance().getRulesetPathDir() != null) { + String filePath = DocSettings.getInstance().getRulesetPathDir(); + filePath += File.separator + file.getClassName().substring(file.getClassName().lastIndexOf(".") + 1) + ".crysl"; + fileContent = readCryslFile(filePath); + + } else { + rule = CrySLReader.readRuleFromJarFile(file.getClassName().substring(file.getClassName().lastIndexOf(".") + 1)); + fileContent = readCryslFile(rule.getPath()); + } + //String filePath = DocSettings.getInstance().getRulesetPathDir(); + //filePath += File.separator + file.getClassName().substring(file.getClassName().lastIndexOf(".") + 1) + ".crysl"; + //Map> fileContent = readCryslFile(filePath); List objectList = fileContent.get("OBJECTS"); for (String pair : objectList) { diff --git a/src/main/java/de/upb/docgen/crysl/CrySLReader.java b/src/main/java/de/upb/docgen/crysl/CrySLReader.java index 6cbd16b..ea44d78 100644 --- a/src/main/java/de/upb/docgen/crysl/CrySLReader.java +++ b/src/main/java/de/upb/docgen/crysl/CrySLReader.java @@ -1,16 +1,22 @@ package de.upb.docgen.crysl; import java.io.File; - +import java.io.IOException; import java.net.MalformedURLException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import java.security.CodeSource; +import java.util.*; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; -import crypto.cryslhandler.CrySLModelReader; import crypto.exceptions.CryptoAnalysisException; import crypto.rules.CrySLRule; +import crypto.rules.CrySLRuleReader; +import de.upb.docgen.utils.Utils; /** * @author Ritika Singh @@ -18,35 +24,195 @@ public class CrySLReader { - public static List readRulesFromSourceFilesWithoutFiles(final String folderPath) throws CryptoAnalysisException, MalformedURLException { - return new ArrayList<>(readRulesFromSourceFiles(folderPath).values()); +/* +if (docSettings.getRulesetPathDir() != null) { + rules = ruleReader.readFromDirectory(new File(docSettings.getRulesetPathDir())); + //Generate dot files from given ruleset + if(docSettings.isBooleanE()) { + System.out.println("Generating the statemachine files from " + docSettings.getRulesetPathDir() + "."); + StateMachineToGraphviz.generateGraphvizStateMachines(docSettings.getRulesetPathDir(),docSettings.getReportDirectory()); + } + } else { + //read rules from jar resources + rules = CrySLReader.readRulesFromJar(); + //generate dot files from jar resources + if(docSettings.isBooleanE()) { + System.out.println("Generating the statemachine files from default resources."); + StateMachineToGraphviz.generateGraphvizStateMachines(docSettings.getReportDirectory()); + } + } + */ + + + public static List readRulesFromJar() throws IOException, CryptoAnalysisException { + + final String path = "CrySLRules"; + final File jarFile = new File(CrySLReader.class.getProtectionDomain().getCodeSource().getLocation().getPath()); + CrySLRuleReader cryslmodelreader = new CrySLRuleReader(); + + List rules = new ArrayList<>(); + + if(jarFile.isFile()) { // Run with JAR file + final JarFile jar = new JarFile(jarFile); + final Enumeration entries = jar.entries(); //gives ALL entries in jar + while (entries.hasMoreElements()) { + try { + final JarEntry name = entries.nextElement(); + if (name.getName().endsWith(".crysl")) { //only handle crysl files + File extractedRule = Utils.extract(name.getName()); //Create a temporary crysl file + String shortend = extractedRule.getName().substring(0, extractedRule.getName().indexOf("crysl") + "crysl".length()); //CrySL Rule name without temp file ending + Files.move(extractedRule.toPath(), Paths.get(shortend), StandardCopyOption.REPLACE_EXISTING); + File renamedTempFile = (Paths.get(shortend).toFile()); + CrySLRule rule = cryslmodelreader.readFromSourceFile(renamedTempFile); //Renaming allows the file to be read by the CrySLModelReader + renamedTempFile.deleteOnExit(); //Removes the temp CrySL file after jvm is finished + rules.add(rule); + + } + } catch (CryptoAnalysisException ex ) { + System.err.println("Error processing: " + " - " + ex.getMessage()); + } + + } + jar.close(); + + + } else { // Run with IDE + final URL url = CrySLReader.class.getResource("/" + path); + if (url != null) { + try { + final File apps = new File(url.toURI()); + for (File file : apps.listFiles()) { + try { + rules.add(cryslmodelreader.readFromSourceFile(file)); + } catch (CryptoAnalysisException ex) { + System.err.println("Error processing file: " + file.getName() + " - " + ex.getMessage()); + } + } + } catch (URISyntaxException ex) { + System.err.println("URI syntax error: " + ex.getMessage()); + } + } + } + return rules; + + + } + + + public static File readRuleFromJarFile(String ruleName) throws IOException, CryptoAnalysisException { + + final String path = "CrySLRules"; + final CodeSource codeSource = CrySLReader.class.getProtectionDomain().getCodeSource(); + final File jarFile = new File(codeSource.getLocation().getPath()); + if (jarFile.isFile()) { // Run with JAR file + try (JarFile jar = new JarFile(jarFile)) { + final Enumeration entries = jar.entries(); // gives ALL entries in jar + while (entries.hasMoreElements()) { + final JarEntry entry = entries.nextElement(); + if (entry.getName().endsWith(".crysl") && entry.getName().contains(ruleName)) { // only handle crysl files + File extractedRule = Utils.extract(entry.getName()); // Create a temporary crysl file + String shortName = extractedRule.getName().substring(0, extractedRule.getName().indexOf("crysl") + "crysl".length()); // CrySL Rule name without temp file ending + Files.move(extractedRule.toPath(), Paths.get(shortName), StandardCopyOption.REPLACE_EXISTING); + File renamedTempFile = (Paths.get(shortName).toFile()); + renamedTempFile.deleteOnExit(); // Removes the temp CrySL file after JVM is finished + return renamedTempFile; + } + } + } + } else { // Run with IDE + final URL url = CrySLReader.class.getResource("/" + path); + if (url != null) { + try { + final File apps = new File(url.toURI()); + for (File file : apps.listFiles()) { + if (file.getName().contains(ruleName)) { + return file; + } + } + } catch (URISyntaxException ex) { + // Handle exception + } + } + } + return null; } - public static Map readRulesFromSourceFiles(final String folderPath) throws CryptoAnalysisException, MalformedURLException { - if (folderPath == null || folderPath.isEmpty()) { - throw new IllegalArgumentException("Folder path cannot be null or empty"); + + public static File readSymbolPropertiesFromJar() { + final String path = "Templates" + "/" + "symbol.properties"; + final CodeSource codeSource = CrySLReader.class.getProtectionDomain().getCodeSource(); + final File jarFile = new File(codeSource.getLocation().getPath()); + + if (jarFile.isFile()) { // Run with JAR file + try (JarFile jar = new JarFile(jarFile)) { + final Enumeration entries = jar.entries(); // gives ALL entries in jar + while (entries.hasMoreElements()) { + final JarEntry entry = entries.nextElement(); + if (entry.getName().endsWith(".properties")) { // only handle crysl files + File extractedRule = Utils.extract(entry.getName()); // Create a temporary crysl file + String shortName = extractedRule.getName().substring(0, extractedRule.getName().indexOf("properties") + "properties".length()); // CrySL Rule name without temp file ending + Files.move(extractedRule.toPath(), Paths.get(shortName), StandardCopyOption.REPLACE_EXISTING); + File renamedTempFile = (Paths.get(shortName).toFile()); + renamedTempFile.deleteOnExit(); // Removes the temp CrySL file after JVM is finished + return renamedTempFile; + } + } + } catch (IOException e) { + e.printStackTrace(); + } + } else { // Run with IDE + final URL url = CrySLReader.class.getResource("/" + path); + if (url != null) { + try { + final File apps = new File(url.toURI()); + return apps; + } catch (URISyntaxException ex) { + // Handle exception + } + } } + return null; + } + + + + public static File readFTLFromJar(String FTLname) throws IOException { + + final String path = "FTLTemplates" + "/" + FTLname; + final File jarFile = new File(CrySLReader.class.getProtectionDomain().getCodeSource().getLocation().getPath()); - CrySLModelReader cryslModelReader = new CrySLModelReader(); - Map rules = new HashMap<>(); - try { - File folder = new File(folderPath); - if (!folder.isDirectory()) { - throw new IllegalArgumentException("Invalid folder path: " + folderPath); + + if(jarFile.isFile()) { // Run with JAR file + final JarFile jar = new JarFile(jarFile); + final Enumeration entries = jar.entries(); //gives ALL entries in jar + while(entries.hasMoreElements()) { + final JarEntry name = entries.nextElement(); + if (name.getName().contains(FTLname)) { //only handle crysl files + File extractedRule = Utils.extract(name.getName()); //Create a temporary crysl file + String shortend = extractedRule.getName().substring(0,extractedRule.getName().indexOf("ftl")+"ftl".length()); //CrySL Rule name without temp file ending + Files.move(extractedRule.toPath(), Paths.get(shortend), StandardCopyOption.REPLACE_EXISTING); + File renamedTempFile = (Paths.get(shortend).toFile()); + renamedTempFile.deleteOnExit(); //Removes the temp CrySL file after jvm is finished + return renamedTempFile; + + } } + jar.close(); - for (File file : folder.listFiles()) { - if (file.getName().endsWith(".crysl")) { - rules.put(file, cryslModelReader.readRule(file)); + } else { // Run with IDE + final URL url = CrySLReader.class.getResource("/" + path); + if (url != null) { + try { + final File apps = new File(url.toURI()); + return apps; + } catch (URISyntaxException ex) { + // Handle exception } } - } catch (CryptoAnalysisException e) { - // Handle CryptoAnalysisException - throw e; } + return null; - return rules; - } + } } \ No newline at end of file diff --git a/src/main/java/de/upb/docgen/utils/FTLTemplateLoaderFromJar.java b/src/main/java/de/upb/docgen/utils/FTLTemplateLoaderFromJar.java new file mode 100644 index 0000000..c8c0d4d --- /dev/null +++ b/src/main/java/de/upb/docgen/utils/FTLTemplateLoaderFromJar.java @@ -0,0 +1,16 @@ +package de.upb.docgen.utils; + +import de.upb.docgen.Order; + +import java.io.File; +import java.io.IOException; + + +public class FTLTemplateLoaderFromJar { + public static File readFtlTemplateFromJar(String templateName) throws IOException { + String pathToLangTemplates = Order.class.getResource("/FTLTemplates").getPath(); + String folderName = pathToLangTemplates.substring(pathToLangTemplates.lastIndexOf("/") + 1); + File template = Utils.extract(folderName + "/" + templateName); + return template; + } +} diff --git a/src/main/java/de/upb/docgen/utils/TreeNode.java b/src/main/java/de/upb/docgen/utils/TreeNode.java index 6dfef39..3b57943 100644 --- a/src/main/java/de/upb/docgen/utils/TreeNode.java +++ b/src/main/java/de/upb/docgen/utils/TreeNode.java @@ -8,7 +8,7 @@ public class TreeNode{ private T data = null; - private List children = new ArrayList<>(); + private final List children = new ArrayList<>(); private TreeNode parent = null; public TreeNode(T data) { diff --git a/src/main/java/de/upb/docgen/utils/Utils.java b/src/main/java/de/upb/docgen/utils/Utils.java index 336d20b..085d5b3 100644 --- a/src/main/java/de/upb/docgen/utils/Utils.java +++ b/src/main/java/de/upb/docgen/utils/Utils.java @@ -7,6 +7,7 @@ import crypto.rules.TransitionEdge; import de.upb.docgen.ComposedRule; import de.upb.docgen.DocSettings; +import de.upb.docgen.Order; import java.io.*; import java.net.URL; @@ -143,7 +144,16 @@ public static Map>>> mapPredicates(Map 0) { +//Write the bytes to the output stream + resourceOS.write(byteArray, 0, i); + } +//Close streams to prevent errors + classIS.close(); + resourceOS.close(); + return f; + } catch (Exception e) { + System.out.println("Error during the file creation process from jar: " + e.getMessage()); + return null; + } + } } diff --git a/src/main/java/de/upb/docgen/writer/FreeMarkerWriter.java b/src/main/java/de/upb/docgen/writer/FreeMarkerWriter.java index 267d2bb..f98f577 100644 --- a/src/main/java/de/upb/docgen/writer/FreeMarkerWriter.java +++ b/src/main/java/de/upb/docgen/writer/FreeMarkerWriter.java @@ -1,7 +1,9 @@ package de.upb.docgen.writer; +import crypto.exceptions.CryptoAnalysisException; import crypto.rules.CrySLRule; import de.upb.docgen.*; +import de.upb.docgen.crysl.CrySLReader; import de.upb.docgen.graphviz.StateMachineToGraphviz; import de.upb.docgen.utils.TemplateAbsolutePathLoader; import de.upb.docgen.utils.TreeNode; @@ -38,7 +40,13 @@ public int compare(ComposedRule o1, ComposedRule o2) { } }); input.put("rules", composedRuleList); - Template template = cfg.getTemplate(Utils.pathForTemplates(DocSettings.getInstance().getFtlTemplatesPath() + "/"+ "sidebar.ftl")); + Template template = null; + if (DocSettings.getInstance().getRulesetPathDir() != null) { + template = cfg.getTemplate(Utils.pathForTemplates(DocSettings.getInstance().getFtlTemplatesPath() + "/" + "sidebar.ftl")); + } else { + template = cfg.getTemplate(CrySLReader.readFTLFromJar("sidebar.ftl").getPath()); + + } // 2.3. Generate the output try (Writer fileWriter = new FileWriter(new File(DocSettings.getInstance().getReportDirectory() + File.separator+"navbar.html"))) { template.process(input, fileWriter); @@ -58,7 +66,7 @@ public int compare(ComposedRule o1, ComposedRule o2) { * @throws IOException * @throws TemplateException */ - public static void createSinglePage(List composedRuleList, Configuration cfg, Map> reqToEns, Map> ensToReq, boolean a, boolean b, boolean c, boolean d, boolean e, boolean f, List crySLRules) throws IOException, TemplateException { + public static void createSinglePage(List composedRuleList, Configuration cfg, Map> reqToEns, Map> ensToReq, boolean a, boolean b, boolean c, boolean d, boolean e, boolean f, List crySLRules) throws IOException, TemplateException, CryptoAnalysisException { for (int i = 0; i < composedRuleList.size(); i++) { ComposedRule rule = composedRuleList.get(i); Map input = new HashMap(); @@ -70,8 +78,12 @@ public static void createSinglePage(List composedRuleList, Configu input.put("ensures", rootEns); // ensures tree parsed by the template // necessary input for the template to load absolute path from crysl rule which can be displayed - input.put("pathToRules", Utils.pathForTemplates("file://" + DocSettings.getInstance().getRulesetPathDir())); - // Set flags + if (DocSettings.getInstance().getRulesetPathDir() != null) { + input.put("pathToRules", Utils.pathForTemplates("file://" + DocSettings.getInstance().getRulesetPathDir())); + } else { + input.put("pathToRules", Utils.pathForTemplates("file://" + CrySLReader.readRuleFromJarFile(composedRuleList.get(i).getOnlyRuleName()).getPath())); + } + // Set flags input.put("booleanA", a); // To show StateMachineGraph input.put("booleanB", b); // To show Help Button input.put("booleanC", c); @@ -82,7 +94,12 @@ public static void createSinglePage(List composedRuleList, Configu input.put("stateMachine", StateMachineToGraphviz.toGraphviz(crySLRules.get(i).getUsagePattern())); // 2.2. Get the template - Template template = cfg.getTemplate(Utils.pathForTemplates(DocSettings.getInstance().getFtlTemplatesPath() + "/" + "singleclass.ftl")); + Template template = null; + if (DocSettings.getInstance().getRulesetPathDir() != null) { + template = cfg.getTemplate(Utils.pathForTemplates(DocSettings.getInstance().getFtlTemplatesPath() + "/" + "singleclass.ftl")); + } else { + template = cfg.getTemplate(CrySLReader.readFTLFromJar("singleclass.ftl").getPath()); + } // create composedRules directory where single pages are stored new File(DocSettings.getInstance().getReportDirectory() + "/" + "composedRules/").mkdir(); @@ -94,10 +111,10 @@ public static void createSinglePage(List composedRuleList, Configu } - /** - * sets freemarker settings - * @param cfg - */ + /** + * sets freemarker settings + * @param cfg + */ public static void setupFreeMarker(Configuration cfg) { // setup freemarker to load absolute paths cfg.setTemplateLoader(new TemplateAbsolutePathLoader()); @@ -115,7 +132,7 @@ public static void setupFreeMarker(Configuration cfg) { */ public static void createCogniCryptLayout(Configuration cfg) throws IOException, TemplateException { Map input = new HashMap(); - + if (!Files.exists(Paths.get(DocSettings.getInstance().getReportDirectory()))) { try { // Attempt to create the directory @@ -127,13 +144,24 @@ public static void createCogniCryptLayout(Configuration cfg) throws IOException, } else { System.out.println("Directory already exists."); } - Template frontpageTemplate = cfg.getTemplate(Utils.pathForTemplates(DocSettings.getInstance().getFtlTemplatesPath() + "/"+ "frontpage.ftl")); - try (Writer fileWriter = new FileWriter(new File(DocSettings.getInstance().getReportDirectory() + File.separator+"frontpage.html"))) { - frontpageTemplate.process(input, fileWriter); - } - Template rootpageTemplate = cfg.getTemplate(Utils.pathForTemplates(DocSettings.getInstance().getFtlTemplatesPath() + "/"+ "rootpage.ftl")); - try (Writer fileWriter = new FileWriter(new File(DocSettings.getInstance().getReportDirectory() + File.separator+"rootpage.html"))) { - rootpageTemplate.process(input, fileWriter); + if (DocSettings.getInstance().getRulesetPathDir() != null) { + Template frontpageTemplate = cfg.getTemplate(Utils.pathForTemplates(DocSettings.getInstance().getFtlTemplatesPath() + "/"+ "frontpage.ftl")); + try (Writer fileWriter = new FileWriter(new File(DocSettings.getInstance().getReportDirectory() + File.separator+"frontpage.html"))) { + frontpageTemplate.process(input, fileWriter); + } + Template rootpageTemplate = cfg.getTemplate(Utils.pathForTemplates(DocSettings.getInstance().getFtlTemplatesPath() + "/"+ "rootpage.ftl")); + try (Writer fileWriter = new FileWriter(new File(DocSettings.getInstance().getReportDirectory() + File.separator+"rootpage.html"))) { + rootpageTemplate.process(input, fileWriter); + } + } else { + Template frontpageTemplate = cfg.getTemplate(CrySLReader.readFTLFromJar("frontpage.ftl").getPath()); + try (Writer fileWriter = new FileWriter(new File(DocSettings.getInstance().getReportDirectory() + File.separator+"frontpage.html"))) { + frontpageTemplate.process(input, fileWriter); + } + Template rootpageTemplate = cfg.getTemplate(CrySLReader.readFTLFromJar("rootpage.ftl").getPath()); + try (Writer fileWriter = new FileWriter(new File(DocSettings.getInstance().getReportDirectory() + File.separator+"rootpage.html"))) { + rootpageTemplate.process(input, fileWriter); + } } } } diff --git a/src/main/resources/FTLTemplates/singleclass.ftl b/src/main/resources/FTLTemplates/singleclass.ftl index 32557dc..9eeea96 100644 --- a/src/main/resources/FTLTemplates/singleclass.ftl +++ b/src/main/resources/FTLTemplates/singleclass.ftl @@ -93,6 +93,20 @@ outline: none; } + .toggle-icon { + cursor: pointer; + margin-right: 5px; + font-weight: bold; + font-size: 14px; + display: inline-block; + width: 15px; /* Adjust width for alignment */ + text-align: center; /* Center align the + or - */ + } + + .tree-node a { + cursor: pointer; + } + .collapsible { background-color: #777; @@ -342,9 +356,14 @@ <#macro reqTree treenode> - ${treenode.data} <#if treenode.children?has_content> - + + + #if> + + ${treenode.data} + + <#if treenode.children?has_content> + <#list treenode.children as child> <@reqTree child /> #list> @@ -373,9 +392,14 @@ <#macro ensTree treenode> - ${treenode.data} <#if treenode.children?has_content> - + + + #if> + + ${treenode.data} + + <#if treenode.children?has_content> + <#list treenode.children as child> <@ensTree child /> #list> @@ -416,8 +440,8 @@ The CrySL rule on Github. - "${pathToRules}/${rule.onlyRuleName}.crysl"<#else>"../rules/${rule.onlyRuleName}.crysl"#if> - onload='javascript:(function(o){o.style.height=o.contentWindow.document.body.scrollHeight+"px";}(this));' + #if> @@ -469,6 +493,34 @@ window.toggleAll = window.toggleAll === 0 ? 1 : 0; } + function toggleNode(element) { + // Get the UL containing the child nodes + var childUl = element.nextElementSibling.nextElementSibling; + + // Toggle the visibility of the child UL + if (childUl) { + if (childUl.style.display === "none") { + childUl.style.display = "block"; + element.textContent = "-"; // Change to minus when expanded + } else { + childUl.style.display = "none"; + element.textContent = "+"; // Change to plus when collapsed + } + } + } + + window.onload = function() { + var treeNodes = document.querySelectorAll('.tree > li > ul'); + treeNodes.forEach(function(ul) { + ul.style.display = 'none'; + }); + + var toggleIcons = document.querySelectorAll('.tree li .toggle-icon'); + toggleIcons.forEach(function(icon) { + icon.textContent = "+"; // Set all initial icons to plus + }); + } + function toggle() { var btn = document.getElementById("toggleBtn"); if (btn.value === "Hide Help") { diff --git a/src/main/resources/Templates/ConstraintsVCClauseCon b/src/main/resources/Templates/ConstraintsVcClauseCon similarity index 100% rename from src/main/resources/Templates/ConstraintsVCClauseCon rename to src/main/resources/Templates/ConstraintsVcClauseCon
The CrySL rule on Github.