Cleaned up reporting

Former-commit-id: 87f2ddb1f8e9d764cf641d86bed23cbec4b509d7
This commit is contained in:
Jeremy Long
2012-11-17 07:57:55 -05:00
parent ce1ed46851
commit 0f2752220a
6 changed files with 116 additions and 56 deletions

View File

@@ -243,6 +243,9 @@ along with DependencyCheck. If not, see <http://www.gnu.org/licenses/>.
<value>target/data/cpe</value> <value>target/data/cpe</value>
</property> </property>
</systemProperties> </systemProperties>
<includes>
<include>**/*IntegrationTest.java</include>
</includes>
</configuration> </configuration>
<executions> <executions>
<execution> <execution>

View File

@@ -28,6 +28,7 @@ import java.util.logging.LogManager;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.ParserConfigurationException;
import org.apache.commons.cli.ParseException; import org.apache.commons.cli.ParseException;
import org.codesecure.dependencycheck.analyzer.AnalysisPhase;
import org.codesecure.dependencycheck.data.cpe.xml.Importer; import org.codesecure.dependencycheck.data.cpe.xml.Importer;
import org.codesecure.dependencycheck.reporting.ReportGenerator; import org.codesecure.dependencycheck.reporting.ReportGenerator;
import org.codesecure.dependencycheck.dependency.Dependency; import org.codesecure.dependencycheck.dependency.Dependency;
@@ -158,9 +159,9 @@ public class App {
scanner.analyzeDependencies(); scanner.analyzeDependencies();
List<Dependency> dependencies = scanner.getDependencies(); List<Dependency> dependencies = scanner.getDependencies();
ReportGenerator report = new ReportGenerator(); ReportGenerator report = new ReportGenerator(applicationName, dependencies, scanner.getAnalyzers());
try { try {
report.generateReports(reportDirectory, applicationName, dependencies); report.generateReports(reportDirectory);
} catch (IOException ex) { } catch (IOException ex) {
Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex); Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
} catch (Exception ex) { } catch (Exception ex) {

View File

@@ -195,7 +195,8 @@ public class Engine {
try { try {
a.initialize(); a.initialize();
} catch (Exception ex) { } catch (Exception ex) {
Logger.getLogger(Engine.class.getName()).log(Level.SEVERE, "Exception occured initializing " + a.getName() + ".", ex); Logger.getLogger(Engine.class.getName()).log(Level.SEVERE,
"Exception occured initializing " + a.getName() + ".", ex);
try { try {
a.close(); a.close();
} catch (Exception ex1) { } catch (Exception ex1) {
@@ -254,8 +255,23 @@ public class Engine {
try { try {
source.update(); source.update();
} catch (UpdateException ex) { } catch (UpdateException ex) {
Logger.getLogger(Engine.class.getName()).log(Level.SEVERE, "Unable to update " + source.getClass().getName(), ex); Logger.getLogger(Engine.class.getName()).log(Level.SEVERE,
"Unable to update " + source.getClass().getName(), ex);
} }
} }
} }
/**
* Returns a full list of all of the analyzers. This is useful
* for reporting which analyzers where used.
* @return a list of Analyzers
*/
public List<Analyzer> getAnalyzers() {
List<Analyzer> ret = new ArrayList<Analyzer>();
for (AnalysisPhase phase : AnalysisPhase.values()) {
List<Analyzer> analyzerList = analyzers.get(phase);
ret.addAll(analyzerList);
}
return ret;
}
} }

View File

@@ -18,15 +18,15 @@ package org.codesecure.dependencycheck.reporting;
* Copyright (c) 2012 Jeremy Long. All Rights Reserved. * Copyright (c) 2012 Jeremy Long. All Rights Reserved.
*/ */
import java.io.FileInputStream;
import java.io.BufferedWriter; import java.io.BufferedWriter;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import org.apache.velocity.app.VelocityEngine; import org.apache.velocity.app.VelocityEngine;
@@ -35,66 +35,110 @@ import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader; import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
import org.apache.velocity.tools.ToolManager; import org.apache.velocity.tools.ToolManager;
import org.apache.velocity.tools.config.EasyFactoryConfiguration; import org.apache.velocity.tools.config.EasyFactoryConfiguration;
import org.codesecure.dependencycheck.analyzer.Analyzer;
import org.codesecure.dependencycheck.dependency.Dependency; import org.codesecure.dependencycheck.dependency.Dependency;
/** /**
* The ReportGenerator is used to, as the name implies, generate reports. Internally
* the generator uses the Velocity Templating Engine. The ReportGenerator exposes
* a list of Dependencies to the template when generating the report.
* *
* @author Jeremy Long (jeremy.long@gmail.com) * @author Jeremy Long (jeremy.long@gmail.com)
*/ */
public class ReportGenerator { public class ReportGenerator {
/**
* The Velocity Engine.
*/
private VelocityEngine engine = null;
/**
* The Velocity Engine Context.
*/
private Context context = null;
/**
* Constructs a new ReportGenerator.
*
* @param applicationName the application name being analyzed
* @param dependencies the list of dependencies
* @param analyzers the list of analyzers used.
*/
public ReportGenerator(String applicationName, List<Dependency> dependencies, List<Analyzer> analyzers) {
engine = createVelocityEngine();
context = createContext();
engine.init();
context.put("applicationName", applicationName);
context.put("dependencies", dependencies);
context.put("analyzers", analyzers);
}
/**
* Creates a new Velocity Engine.
* @return a velocity engine.
*/
private VelocityEngine createVelocityEngine() {
VelocityEngine ve = new VelocityEngine();
ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
return ve;
}
/**
* Creates a new Velocity Context initialized with escape and date tools.
* @return a Velcotiy Context.
*/
private Context createContext() {
ToolManager manager = new ToolManager();
Context c = manager.createContext();
EasyFactoryConfiguration config = new EasyFactoryConfiguration();
config.addDefaultTools();
config.toolbox("application")
.tool("esc", "org.apache.velocity.tools.generic.EscapeTool")
.tool("org.apache.velocity.tools.generic.DateTool");
manager.configure(config);
return c;
}
/** /**
* Generates the Dependency Reports for the identified dependencies. * Generates the Dependency Reports for the identified dependencies.
* *
* @param outputDir the path where the reports should be written. * @param outputDir the path where the reports should be written.
* @param applicationName the name of the application that was scanned.
* @param dependencies a list of dependencies to include in the report.
* @throws IOException is thrown when the template file does not exist. * @throws IOException is thrown when the template file does not exist.
* @throws Exception is thrown if there is an error writting out the * @throws Exception is thrown if there is an error writting out the
* reports. * reports.
*/ */
public void generateReports(String outputDir, String applicationName, List<Dependency> dependencies) throws IOException, Exception { public void generateReports(String outputDir) throws IOException, Exception {
generateReport("HtmlReport", outputDir + File.separator + "DependencyCheck-Report.html");
Map<String, Object> properties = new HashMap<String, Object>(); //generateReport("XmlReport", outputDir + File.separator + "DependencyCheck-Report.xml");
properties.put("dependencies", dependencies);
properties.put("applicationName", applicationName);
String reportName = applicationName.replaceAll("[^a-zA-Z0-9-_ \\.]+", "");
String filename = outputDir + File.separatorChar + reportName;
generateReport("HtmlReport", filename + ".html", properties);
//generateReport("XmlReport",filename + ".xml",properties);
} }
/** /**
* much of this code is from * Generates a report from a given Velocity Template. The template name
* http://stackoverflow.com/questions/2931516/loading-velocity-template-inside-a-jar-file * provided can be the name of a template contained in the jar file, such as
* 'XmlReport' or 'HtmlReport', or the template name can be the path to a template file.
* *
* @param templateName the name of the template to load. * @param templateName the name of the template to load.
* @param outFileName The filename and path to write the report to. * @param outFileName the filename and path to write the report to.
* @param properties a map of properties to load into the velocity context.
* @throws IOException is thrown when the template file does not exist. * @throws IOException is thrown when the template file does not exist.
* @throws Exception is thrown when an exception occurs. * @throws Exception is thrown when an exception occurs.
*/ */
protected void generateReport(String templateName, String outFileName, public void generateReport(String templateName, String outFileName) throws IOException, Exception {
Map<String, Object> properties) throws IOException, Exception { InputStream input = null;
String templatePath = null;
VelocityEngine ve = new VelocityEngine(); File f = new File(templateName);
ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath"); if (f.exists() && f.isFile()) {
ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName()); try {
templatePath = templateName;
ToolManager manager = new ToolManager(); input = new FileInputStream(f);
Context context = manager.createContext(); } catch (FileNotFoundException ex) {
EasyFactoryConfiguration config = new EasyFactoryConfiguration(); Logger.getLogger(ReportGenerator.class.getName()).log(Level.SEVERE, null, ex);
config.addDefaultTools(); }
config.toolbox("application").tool("esc", "org.apache.velocity.tools.generic.EscapeTool").tool("org.apache.velocity.tools.generic.DateTool"); } else {
templatePath = "templates/" + templateName + ".vsl";
manager.configure(config); input = this.getClass().getClassLoader().getResourceAsStream(templatePath);
}
ve.init();
final String templatePath = "templates/" + templateName + ".vsl";
InputStream input = this.getClass().getClassLoader().getResourceAsStream(templatePath);
if (input == null) { if (input == null) {
throw new IOException("Template file doesn't exist"); throw new IOException("Template file doesn't exist");
} }
@@ -102,19 +146,10 @@ public class ReportGenerator {
InputStreamReader reader = new InputStreamReader(input); InputStreamReader reader = new InputStreamReader(input);
BufferedWriter writer = null; BufferedWriter writer = null;
//VelocityContext context = new VelocityContext();
//load the data into the context
if (properties != null) {
for (Map.Entry<String, Object> property : properties.entrySet()) {
context.put(property.getKey(), property.getValue());
}
}
try { try {
writer = new BufferedWriter(new FileWriter(new File(outFileName))); writer = new BufferedWriter(new FileWriter(new File(outFileName)));
if (!ve.evaluate(context, writer, templatePath, reader)) { if (!engine.evaluate(context, writer, templatePath, reader)) {
throw new Exception("Failed to convert the template into html."); throw new Exception("Failed to convert the template into html.");
} }
writer.flush(); writer.flush();

View File

@@ -285,8 +285,12 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<div class="sectioncontent">Report Generated On: $date<br/><br/> <div class="sectioncontent">Report Generated On: $date<br/><br/>
Dependencies Scanned:&nbsp;$dependencies.size()<br/><br/> Dependencies Scanned:&nbsp;$dependencies.size()<br/><br/>
<div class="indent"> <div class="indent">
#foreach($dependency in $dependencies) #foreach($dependency in $dependencies)
<a href="#$esc.html($esc.url($dependency.FilePath))">$esc.html($dependency.FileName)</a><br/> #if($dependency.getVulnerabilities().size()>0)
<a href="#$esc.html($esc.url($dependency.FilePath))">$esc.html($dependency.FileName)</a>&nbsp;<b style="color:#ff0000;">&#8226;</b><br/>
#else
<a href="#$esc.html($esc.url($dependency.FilePath))">$esc.html($dependency.FileName)</a><br/>
#end
#end #end
</div> </div>
<h2>Dependencies</h2> <h2>Dependencies</h2>

View File

@@ -51,7 +51,8 @@ public class EngineIntegrationTest {
instance.scan(path); instance.scan(path);
assertTrue(instance.getDependencies().size() > 0); assertTrue(instance.getDependencies().size() > 0);
instance.analyzeDependencies(); instance.analyzeDependencies();
ReportGenerator rg = new ReportGenerator(); ReportGenerator rg = new ReportGenerator("DependencyCheck",
rg.generateReports("./target/", "DependencyCheck", instance.getDependencies()); instance.getDependencies(), instance.getAnalyzers());
rg.generateReports("./target/");
} }
} }