mirror of
https://github.com/elisspace/autopsy.git
synced 2026-09-06 02:24:30 +00:00
Updated reporting to work with new tags API
This commit is contained in:
@@ -97,7 +97,7 @@ public class TagsManager implements Closeable {
|
||||
tagNames.clear();
|
||||
tskCase.getTagNamesInUse(tagNames);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks whether a tag name with a given display name exists.
|
||||
* @param [in] tagDisplayName The display name for which to check.
|
||||
@@ -227,6 +227,20 @@ public class TagsManager implements Closeable {
|
||||
tskCase.deleteContentTag(tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all content tags for the current case.
|
||||
* @param [out] tags A list, possibly empty, of content tags.
|
||||
* @throws TskCoreException
|
||||
*/
|
||||
public void getAllContentTags(List<ContentTag> tags) throws TskCoreException {
|
||||
// @@@ This is a work around to be removed when database access on the EDT is correctly synchronized.
|
||||
if (!tagNamesInitialized) {
|
||||
getExistingTagNames();
|
||||
}
|
||||
|
||||
tskCase.getAllContentTags(tags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets content tags count by tag name.
|
||||
* @param [in] tagName The tag name of interest.
|
||||
@@ -297,6 +311,20 @@ public class TagsManager implements Closeable {
|
||||
tskCase.deleteBlackboardArtifactTag(tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all blackboard artifact tags for the current case.
|
||||
* @param [out] tags A list, possibly empty, of blackboard artifact tags.
|
||||
* @throws TskCoreException
|
||||
*/
|
||||
public void getAllBlackboardArtifactTags(List<BlackboardArtifactTag> tags) throws TskCoreException {
|
||||
// @@@ This is a work around to be removed when database access on the EDT is correctly synchronized.
|
||||
if (!tagNamesInitialized) {
|
||||
getExistingTagNames();
|
||||
}
|
||||
|
||||
tskCase.getAllBlackboardArtifactTags(tags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets blackboard artifact tags count by tag name.
|
||||
* @param [in] tagName The tag name of interest.
|
||||
|
||||
@@ -121,40 +121,6 @@ public class ReportExcel implements TableReportModule {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Start a new worksheet for the given data type.
|
||||
* @param name data type name
|
||||
*/
|
||||
@Override
|
||||
public void startDataType(String name) {
|
||||
// Create a worksheet for the data type (assumed to be an artifact type).
|
||||
name = escapeForExcel(name);
|
||||
sheet = wb.createSheet(name);
|
||||
sheet.setAutobreaks(true);
|
||||
rowIndex = 0;
|
||||
artifactsCount = 0;
|
||||
|
||||
// Add a title row to the worksheet.
|
||||
Row row = sheet.createRow(rowIndex);
|
||||
row.setRowStyle(setStyle);
|
||||
row.createCell(0).setCellValue(name);
|
||||
++rowIndex;
|
||||
|
||||
// Add an artifacts count row. The actual count will be filled in later.
|
||||
row = sheet.createRow(rowIndex);
|
||||
row.setRowStyle(setStyle);
|
||||
row.createCell(0).setCellValue("Number of artifacts:");
|
||||
++rowIndex;
|
||||
|
||||
// Add an empty row as a separator.
|
||||
sheet.createRow(rowIndex);
|
||||
++rowIndex;
|
||||
|
||||
// There will be at least two columns, one each for the artifacts count and its label.
|
||||
sheetColCount = 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a new worksheet for the given data type.
|
||||
* Note: This method is a temporary workaround to avoid modifying the TableReportModule interface.
|
||||
@@ -162,7 +128,8 @@ public class ReportExcel implements TableReportModule {
|
||||
* @param name Name of the data type
|
||||
* @param comment Comment on the data type, may be the empty string
|
||||
*/
|
||||
public void startDataType(String name, String comment) {
|
||||
@Override
|
||||
public void startDataType(String name, String description) {
|
||||
// Create a worksheet for the data type (assumed to be an artifact type).
|
||||
name = escapeForExcel(name);
|
||||
sheet = wb.createSheet(name);
|
||||
@@ -183,10 +150,10 @@ public class ReportExcel implements TableReportModule {
|
||||
++rowIndex;
|
||||
|
||||
// Add a comment row, if a comment was supplied.
|
||||
if (!comment.isEmpty()) {
|
||||
if (!description.isEmpty()) {
|
||||
row = sheet.createRow(rowIndex);
|
||||
row.setRowStyle(setStyle);
|
||||
row.createCell(0).setCellValue(comment);
|
||||
row.createCell(0).setCellValue(description);
|
||||
++rowIndex;
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,6 @@ import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.coreutils.EscapeUtil;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||
import org.sleuthkit.autopsy.datamodel.Tags;
|
||||
import org.sleuthkit.autopsy.report.ReportProgressPanel.ReportStatus;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
@@ -58,16 +57,15 @@ import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifactTag;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
|
||||
import org.sleuthkit.datamodel.ContentTag;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
* Generates all TableReportModules and GeneralReportModules, given whether each module for both
|
||||
* types is enabled or disabled, and the base report path to save them at.
|
||||
*
|
||||
* After creating an instance of ReportGenerator, one must tell it which reports to run,
|
||||
* TableReportModules on Tags or Artifacts, and the GeneralReportModules.
|
||||
* Then, one calls displayProgressPanels() to display the progress to the user.
|
||||
* Instances of this class use GeneralReportModules, TableReportModules and
|
||||
* FileReportModules to generate a report. If desired, displayProgressPanels()
|
||||
* can be called to show report generation progress using ReportProgressPanel
|
||||
* objects displayed using a dialog box.
|
||||
*/
|
||||
public class ReportGenerator {
|
||||
private static final Logger logger = Logger.getLogger(ReportGenerator.class.getName());
|
||||
@@ -106,10 +104,11 @@ public class ReportGenerator {
|
||||
}
|
||||
|
||||
/**
|
||||
* For every ReportModule which the user enabled, create a ReportProgressPanel for that report.
|
||||
* Create a ReportProgressPanel for each report generation module selected by the user.
|
||||
*
|
||||
* @param tableModuleStates the enabled/disabled state of each TableReportModule
|
||||
* @param generalModuleStates the enabled/disabled state of each GeneralReportModule
|
||||
* @param tableModuleStates The enabled/disabled state of each TableReportModule
|
||||
* @param generalModuleStates The enabled/disabled state of each GeneralReportModule
|
||||
* @param fileListModuleStates The enabled/disabled state of each FileReportModule
|
||||
*/
|
||||
private void setupProgressPanels(Map<TableReportModule, Boolean> tableModuleStates, Map<GeneralReportModule, Boolean> generalModuleStates, Map<FileReportModule, Boolean> fileListModuleStates) {
|
||||
if (null != tableModuleStates) {
|
||||
@@ -174,28 +173,28 @@ public class ReportGenerator {
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the GeneralReportModule reports in a new SwingWorker.
|
||||
* Run the GeneralReportModules using a SwingWorker.
|
||||
*/
|
||||
public void generateGeneralReports() {
|
||||
GeneralWorker worker = new GeneralWorker();
|
||||
GeneralReportsWorker worker = new GeneralReportsWorker();
|
||||
worker.execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the TableReportModule reports on Blackboard Artifacts in a new SwingWorker.
|
||||
* Run the TableReportModules using a SwingWorker.
|
||||
*
|
||||
* @param artifactTypeSelections the enabled/disabled state of the artifact types to be included in the report
|
||||
* @param tagSelections the enabled/disabled state of the tags to be included in the report
|
||||
* @param tagSelections the enabled/disabled state of the tag names to be included in the report
|
||||
*/
|
||||
public void generateArtifactTableReports(Map<ARTIFACT_TYPE, Boolean> artifactTypeSelections, Map<String, Boolean> tagSelections) {
|
||||
public void generateBlackboardArtifactsReports(Map<ARTIFACT_TYPE, Boolean> artifactTypeSelections, Map<String, Boolean> tagNameSelections) {
|
||||
if (!tableProgress.isEmpty() && null != artifactTypeSelections) {
|
||||
ArtifactsReportsWorker worker = new ArtifactsReportsWorker(artifactTypeSelections, tagSelections);
|
||||
TableReportsWorker worker = new TableReportsWorker(artifactTypeSelections, tagNameSelections);
|
||||
worker.execute();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the FileReportModule reports in a new SwingWorker.
|
||||
* Run the FileReportModules using a SwingWorker.
|
||||
*
|
||||
* @param enabledInfo the Information that should be included about each file
|
||||
* in the report.
|
||||
@@ -214,9 +213,9 @@ public class ReportGenerator {
|
||||
}
|
||||
|
||||
/**
|
||||
* SwingWorker to generate a report on all GeneralReportModules.
|
||||
* SwingWorker to run GeneralReportModules.
|
||||
*/
|
||||
private class GeneralWorker extends SwingWorker<Integer, Integer> {
|
||||
private class GeneralReportsWorker extends SwingWorker<Integer, Integer> {
|
||||
|
||||
@Override
|
||||
protected Integer doInBackground() throws Exception {
|
||||
@@ -232,7 +231,7 @@ public class ReportGenerator {
|
||||
}
|
||||
|
||||
/**
|
||||
* SwingWorker to generate a FileReport.
|
||||
* SwingWorker to run FileReportModules.
|
||||
*/
|
||||
private class FileReportsWorker extends SwingWorker<Integer, Integer> {
|
||||
private List<FileReportDataTypes> enabledInfo = Arrays.asList(FileReportDataTypes.values());
|
||||
@@ -317,15 +316,15 @@ public class ReportGenerator {
|
||||
}
|
||||
|
||||
/**
|
||||
* SwingWorker to generate reports on blackboard artifacts.
|
||||
* SwingWorker to run TableReportModules to report on blackboard artifacts,
|
||||
* content tags, and blackboard artifact tags.
|
||||
*/
|
||||
private class ArtifactsReportsWorker extends SwingWorker<Integer, Integer> {
|
||||
private class TableReportsWorker extends SwingWorker<Integer, Integer> {
|
||||
private List<TableReportModule> tableModules = new ArrayList<>();
|
||||
private List<ARTIFACT_TYPE> artifactTypes = new ArrayList<>();
|
||||
private HashSet<String> tagNamesFilter = new HashSet<>();
|
||||
|
||||
// Create an ArtifactWorker with the enabled/disabled state of all Artifacts
|
||||
ArtifactsReportsWorker(Map<ARTIFACT_TYPE, Boolean> artifactTypeSelections, Map<String, Boolean> tagSelections) {
|
||||
TableReportsWorker(Map<ARTIFACT_TYPE, Boolean> artifactTypeSelections, Map<String, Boolean> tagNameSelections) {
|
||||
// Get the report modules selected by the user.
|
||||
for (Entry<TableReportModule, ReportProgressPanel> entry : tableProgress.entrySet()) {
|
||||
tableModules.add(entry.getKey());
|
||||
@@ -338,9 +337,9 @@ public class ReportGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
// Get the tags selected by the user.
|
||||
if (null != tagSelections) {
|
||||
for (Entry<String, Boolean> entry : tagSelections.entrySet()) {
|
||||
// Get the tag names selected by the user and make a tag names filter.
|
||||
if (null != tagNameSelections) {
|
||||
for (Entry<String, Boolean> entry : tagNameSelections.entrySet()) {
|
||||
if (entry.getValue() == true) {
|
||||
tagNamesFilter.add(entry.getKey());
|
||||
}
|
||||
@@ -350,39 +349,46 @@ public class ReportGenerator {
|
||||
|
||||
@Override
|
||||
protected Integer doInBackground() throws Exception {
|
||||
// Start the report
|
||||
// Start the progress indicators for each active TableReportModule.
|
||||
for (TableReportModule module : tableModules) {
|
||||
ReportProgressPanel progress = tableProgress.get(module);
|
||||
if (progress.getStatus() != ReportStatus.CANCELED) {
|
||||
module.startReport(reportPath);
|
||||
progress.start();
|
||||
progress.setIndeterminate(false);
|
||||
progress.setMaximumProgress(ARTIFACT_TYPE.values().length);
|
||||
progress.setMaximumProgress(ARTIFACT_TYPE.values().length + 2); // +2 for content and blackboard artifact tags
|
||||
}
|
||||
}
|
||||
|
||||
makeBlackboardArtifactTables();
|
||||
makeContentTagsTables();
|
||||
makeBlackboardArtifactTagsTables();
|
||||
|
||||
// Make a comment on the tags filter.
|
||||
for (TableReportModule module : tableModules) {
|
||||
tableProgress.get(module).complete();
|
||||
module.endReport();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void makeBlackboardArtifactTables() {
|
||||
// Make a comment string describing the tag names filter in effect.
|
||||
StringBuilder comment = new StringBuilder();
|
||||
if (!tagNamesFilter.isEmpty()) {
|
||||
comment.append("This report only includes files and artifacts tagged with: ");
|
||||
comment.append("This report only includes results tagged with: ");
|
||||
comment.append(makeCommaSeparatedList(tagNamesFilter));
|
||||
}
|
||||
|
||||
// For every enabled artifact type
|
||||
|
||||
// Add a table to the report for every enabled blackboard artifact type.
|
||||
for (ARTIFACT_TYPE type : artifactTypes) {
|
||||
// Check to see if all the TableReportModules have been canceled
|
||||
// Check for cancellaton.
|
||||
removeCancelledTableReportModules();
|
||||
if (tableModules.isEmpty()) {
|
||||
break;
|
||||
return;
|
||||
}
|
||||
Iterator<TableReportModule> iter = tableModules.iterator();
|
||||
while (iter.hasNext()) {
|
||||
TableReportModule module = iter.next();
|
||||
if (tableProgress.get(module).getStatus() == ReportStatus.CANCELED) {
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
|
||||
// If the type is keyword hit or hashset hit, use the helper
|
||||
|
||||
// Keyword hits and hashset hit artifacts get sepcial handling.
|
||||
if (type.equals(ARTIFACT_TYPE.TSK_KEYWORD_HIT)) {
|
||||
writeKeywordHits(tableModules, comment.toString(), tagNamesFilter);
|
||||
continue;
|
||||
@@ -392,20 +398,19 @@ public class ReportGenerator {
|
||||
}
|
||||
|
||||
List<ArtifactData> unsortedArtifacts = getFilteredArtifacts(type, tagNamesFilter);
|
||||
|
||||
if (unsortedArtifacts.isEmpty()) {
|
||||
// Don't report on this artifact type if there are no results
|
||||
continue;
|
||||
}
|
||||
|
||||
// The most efficient way to sort all the Artifacts is to add them to a List, and then
|
||||
// sort that List based off a Comparator. Adding to a TreeMap/Set/List sorts the list
|
||||
// each time an element is added, which adds unnecessary overhead if we only need it sorted once.
|
||||
Collections.sort(unsortedArtifacts);
|
||||
|
||||
// Get the column headers appropriate for the artifact type.
|
||||
/* @@@ BC: Seems like a better design here woudl be to have a method that
|
||||
* takes in teh artifact as an argument andreturns the attributes. We then use that
|
||||
* to make the headers and to make each row afterwards so that we don't ahve artifact-specific
|
||||
/* @@@ BC: Seems like a better design here would be to have a method that
|
||||
* takes in the artifact as an argument and returns the attributes. We then use that
|
||||
* to make the headers and to make each row afterwards so that we don't have artifact-specific
|
||||
* logic in both getArtifactTableCoumnHeaders and getArtifactRow()
|
||||
*/
|
||||
List<String> columnHeaders = getArtifactTableColumnHeaders(type.getTypeID());
|
||||
@@ -414,37 +419,17 @@ public class ReportGenerator {
|
||||
MessageNotifyUtil.Notify.show("Skipping artifact type " + type + " in reports", "Unknown columns to report on", MessageNotifyUtil.MessageType.ERROR);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
for (TableReportModule module : tableModules) {
|
||||
tableProgress.get(module).updateStatusLabel("Now processing " + type.getDisplayName() + "...");
|
||||
|
||||
// This is a temporary workaround to avoid modifying the TableReportModule interface.
|
||||
if (module instanceof ReportHTML) {
|
||||
ReportHTML htmlReportModule = (ReportHTML)module;
|
||||
htmlReportModule.startDataType(type.getDisplayName(), comment.toString());
|
||||
htmlReportModule.startTable(columnHeaders, type);
|
||||
}
|
||||
else if (module instanceof ReportExcel) {
|
||||
ReportExcel excelReportModule = (ReportExcel)module;
|
||||
excelReportModule.startDataType(type.getDisplayName(), comment.toString());
|
||||
excelReportModule.startTable(columnHeaders);
|
||||
}
|
||||
else {
|
||||
module.startDataType(type.getDisplayName());
|
||||
module.startTable(columnHeaders);
|
||||
}
|
||||
module.startDataType(type.getDisplayName(), comment.toString());
|
||||
module.startTable(columnHeaders);
|
||||
}
|
||||
|
||||
|
||||
boolean msgSent = false;
|
||||
for(ArtifactData artifactData : unsortedArtifacts) {
|
||||
// HashSet<String> tags = artifactData.getTags();
|
||||
//
|
||||
// String tagsList = makeCommaSeparatedList(tags);
|
||||
|
||||
for(ArtifactData artifactData : unsortedArtifacts) {
|
||||
// Add the row data to all of the reports.
|
||||
for (TableReportModule module : tableModules) {
|
||||
|
||||
// Get the row data for this type of artifact.
|
||||
for (TableReportModule module : tableModules) {
|
||||
List<String> rowData;
|
||||
rowData = getArtifactRow(artifactData, module);
|
||||
if (rowData.isEmpty()) {
|
||||
@@ -455,44 +440,160 @@ public class ReportGenerator {
|
||||
continue;
|
||||
}
|
||||
|
||||
// // This is a temporary workaround to avoid modifying the TableReportModule interface.
|
||||
// if (module instanceof ReportHTML) {
|
||||
// ReportHTML htmlReportModule = (ReportHTML)module;
|
||||
// htmlReportModule.addRow(rowData, artifactData.getArtifact());
|
||||
// }
|
||||
// else {
|
||||
module.addRow(rowData);
|
||||
// }
|
||||
module.addRow(rowData);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Finish up this data type
|
||||
for (TableReportModule module : tableModules) {
|
||||
tableProgress.get(module).increment();
|
||||
module.endTable();
|
||||
module.endDataType();
|
||||
}
|
||||
}
|
||||
|
||||
// End the report
|
||||
for (TableReportModule module : tableModules) {
|
||||
tableProgress.get(module).complete();
|
||||
module.endReport();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void makeContentTagsTables() {
|
||||
// Check for cancellaton.
|
||||
removeCancelledTableReportModules();
|
||||
if (tableModules.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the content tags.
|
||||
ArrayList<ContentTag> tags = new ArrayList<>();
|
||||
try {
|
||||
Case.getCurrentCase().getServices().getTagsManager().getAllContentTags(tags);
|
||||
}
|
||||
catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "failed to get content tags", ex);
|
||||
return;
|
||||
}
|
||||
|
||||
// Tell the modules reporting on content tags is beginning.
|
||||
for (TableReportModule module : tableModules) {
|
||||
// @@@ This casting is a tricky little workaround to allow the HTML report module to slip in a content hyperlink.
|
||||
// @@@ Alos Using the obsolete ARTIFACT_TYPE.TSK_TAG_FILE is also an expedient hack.
|
||||
tableProgress.get(module).updateStatusLabel("Now processing " + ARTIFACT_TYPE.TSK_TAG_FILE.getDisplayName() + "...");
|
||||
ArrayList<String> columnHeaders = new ArrayList<>(Arrays.asList("File", "Tag", "Comment"));
|
||||
StringBuilder comment = new StringBuilder();
|
||||
if (!tagNamesFilter.isEmpty()) {
|
||||
comment.append("This report only includes file tagged with: ");
|
||||
comment.append(makeCommaSeparatedList(tagNamesFilter));
|
||||
}
|
||||
if (module instanceof ReportHTML) {
|
||||
ReportHTML htmlReportModule = (ReportHTML)module;
|
||||
htmlReportModule.startDataType(ARTIFACT_TYPE.TSK_TAG_FILE.getDisplayName(), comment.toString());
|
||||
htmlReportModule.startContentTagsTable(columnHeaders);
|
||||
}
|
||||
else {
|
||||
module.startDataType(ARTIFACT_TYPE.TSK_TAG_FILE.getDisplayName(), comment.toString());
|
||||
module.startTable(columnHeaders);
|
||||
}
|
||||
}
|
||||
|
||||
// Give the modules the rows for the content tags.
|
||||
for (ContentTag tag : tags) {
|
||||
// Apply the tag names filter.
|
||||
if (!tagNamesFilter.isEmpty()) {
|
||||
if (tagNamesFilter.contains(tag.getName().getDisplayName())) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList<String> rowData = new ArrayList<>(Arrays.asList(tag.getContent().getName(), tag.getName().getDisplayName(), tag.getComment()));
|
||||
for (TableReportModule module : tableModules) {
|
||||
// @@@ This casting is a tricky little workaround to allow the HTML report module to slip in a content hyperlink.
|
||||
if (module instanceof ReportHTML) {
|
||||
ReportHTML htmlReportModule = (ReportHTML)module;
|
||||
htmlReportModule.addRowWithTaggedContentHyperlink(rowData, tag);
|
||||
}
|
||||
else {
|
||||
module.addRow(rowData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The the modules content tags reporting is ended.
|
||||
for (TableReportModule module : tableModules) {
|
||||
tableProgress.get(module).increment();
|
||||
module.endTable();
|
||||
module.endDataType();
|
||||
}
|
||||
}
|
||||
|
||||
private void makeBlackboardArtifactTagsTables() {
|
||||
// Check for cancellaton.
|
||||
removeCancelledTableReportModules();
|
||||
if (tableModules.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ArrayList<BlackboardArtifactTag> tags = new ArrayList<>();
|
||||
try {
|
||||
Case.getCurrentCase().getServices().getTagsManager().getAllBlackboardArtifactTags(tags);
|
||||
}
|
||||
catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "failed to get blackboard artifact tags", ex);
|
||||
return;
|
||||
}
|
||||
|
||||
// Tell the modules reporting on blackboard artifact tags data type is beginning.
|
||||
// @@@ Using the obsolete ARTIFACT_TYPE.TSK_TAG_ARTIFACT is an expedient hack.
|
||||
for (TableReportModule module : tableModules) {
|
||||
tableProgress.get(module).updateStatusLabel("Now processing " + ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getDisplayName() + "...");
|
||||
StringBuilder comment = new StringBuilder();
|
||||
if (!tagNamesFilter.isEmpty()) {
|
||||
comment.append("This report only includes results tagged with: ");
|
||||
comment.append(makeCommaSeparatedList(tagNamesFilter));
|
||||
}
|
||||
module.startDataType(ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getDisplayName(), comment.toString());
|
||||
module.startTable(new ArrayList<>(Arrays.asList("Result Type", "Tag", "Comment", "Source File")));
|
||||
}
|
||||
|
||||
// Give the modules the rows for the content tags.
|
||||
for (BlackboardArtifactTag tag : tags) {
|
||||
// Apply the tag names filter.
|
||||
if (!tagNamesFilter.isEmpty()) {
|
||||
if (tagNamesFilter.contains(tag.getName().getDisplayName())) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
for (TableReportModule module : tableModules) {
|
||||
module.addRow(new ArrayList<>(Arrays.asList(tag.getArtifact().getArtifactTypeName(), tag.getName().getDisplayName(), tag.getComment(), tag.getContent().getName())));
|
||||
}
|
||||
}
|
||||
|
||||
// The the modules blackboard artifact tags reporting is ended.
|
||||
for (TableReportModule module : tableModules) {
|
||||
tableProgress.get(module).increment();
|
||||
module.endTable();
|
||||
module.endDataType();
|
||||
}
|
||||
}
|
||||
|
||||
void removeCancelledTableReportModules() {
|
||||
Iterator<TableReportModule> iter = tableModules.iterator();
|
||||
while (iter.hasNext()) {
|
||||
TableReportModule module = iter.next();
|
||||
if (tableProgress.get(module).getStatus() == ReportStatus.CANCELED) {
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Boolean failsTagFilter(HashSet<String> tags, HashSet<String> tagsFilter)
|
||||
|
||||
/// @@@ Should move the methods specific to TableReportsWorker into that scope.
|
||||
private Boolean failsTagFilter(HashSet<String> tagNames, HashSet<String> tagsNamesFilter)
|
||||
{
|
||||
if (null == tagsFilter || tagsFilter.isEmpty()) {
|
||||
if (null == tagsNamesFilter || tagsNamesFilter.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HashSet<String> filteredTags = new HashSet<>(tags);
|
||||
filteredTags.retainAll(tagsFilter);
|
||||
return filteredTags.isEmpty();
|
||||
HashSet<String> filteredTagNames = new HashSet<>(tagNames);
|
||||
filteredTagNames.retainAll(tagsNamesFilter);
|
||||
return filteredTagNames.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -554,18 +655,7 @@ public class ReportGenerator {
|
||||
|
||||
// Make keyword data type and give them set index
|
||||
for (TableReportModule module : tableModules) {
|
||||
// This is a temporary workaround to avoid modifying the TableReportModule interface.
|
||||
if (module instanceof ReportHTML) {
|
||||
ReportHTML htmlReportModule = (ReportHTML)module;
|
||||
htmlReportModule.startDataType(ARTIFACT_TYPE.TSK_KEYWORD_HIT.getDisplayName(), comment);
|
||||
}
|
||||
else if (module instanceof ReportExcel) {
|
||||
ReportExcel excelReportModule = (ReportExcel)module;
|
||||
excelReportModule.startDataType(ARTIFACT_TYPE.TSK_KEYWORD_HIT.getDisplayName(), comment);
|
||||
}
|
||||
else {
|
||||
module.startDataType(ARTIFACT_TYPE.TSK_KEYWORD_HIT.getDisplayName());
|
||||
}
|
||||
module.startDataType(ARTIFACT_TYPE.TSK_KEYWORD_HIT.getDisplayName(), comment);
|
||||
module.addSetIndex(lists);
|
||||
tableProgress.get(module).updateStatusLabel("Now processing "
|
||||
+ ARTIFACT_TYPE.TSK_KEYWORD_HIT.getDisplayName() + "...");
|
||||
@@ -708,18 +798,7 @@ public class ReportGenerator {
|
||||
}
|
||||
|
||||
for (TableReportModule module : tableModules) {
|
||||
// This is a temporary workaround to avoid modifying the TableReportModule interface.
|
||||
if (module instanceof ReportHTML) {
|
||||
ReportHTML htmlReportModule = (ReportHTML)module;
|
||||
htmlReportModule.startDataType(ARTIFACT_TYPE.TSK_HASHSET_HIT.getDisplayName(), comment);
|
||||
}
|
||||
else if (module instanceof ReportExcel) {
|
||||
ReportExcel excelReportModule = (ReportExcel)module;
|
||||
excelReportModule.startDataType(ARTIFACT_TYPE.TSK_HASHSET_HIT.getDisplayName(), comment);
|
||||
}
|
||||
else {
|
||||
module.startDataType(ARTIFACT_TYPE.TSK_HASHSET_HIT.getDisplayName());
|
||||
}
|
||||
module.startDataType(ARTIFACT_TYPE.TSK_HASHSET_HIT.getDisplayName(), comment);
|
||||
module.addSetIndex(lists);
|
||||
tableProgress.get(module).updateStatusLabel("Now processing "
|
||||
+ ARTIFACT_TYPE.TSK_HASHSET_HIT.getDisplayName() + "...");
|
||||
@@ -981,7 +1060,7 @@ public class ReportGenerator {
|
||||
* @return List<String> row values
|
||||
* @throws TskCoreException
|
||||
*/
|
||||
private List<String> getArtifactRow(ArtifactData artifactData, TableReportModule module) throws TskCoreException {
|
||||
private List<String> getArtifactRow(ArtifactData artifactData, TableReportModule module) {
|
||||
Map<Integer, String> attributes = getMappedAttributes(artifactData.getAttributes(), module);
|
||||
|
||||
List<String> rowData = new ArrayList<>();
|
||||
@@ -1152,7 +1231,7 @@ public class ReportGenerator {
|
||||
}
|
||||
rowData.add(makeCommaSeparatedList(artifactData.getTags()));
|
||||
|
||||
return rowData; // RJCTODO: Is anyone checking for null here?
|
||||
return rowData;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -28,7 +28,6 @@ import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
@@ -45,17 +44,17 @@ import org.openide.filesystems.FileUtil;
|
||||
import org.openide.util.Exceptions;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.datamodel.Tags;
|
||||
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
||||
import org.sleuthkit.autopsy.datamodel.ContentUtils.ExtractFscContentVisitor;
|
||||
import org.sleuthkit.autopsy.datamodel.Tags;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.Image;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.ContentTag;
|
||||
import org.sleuthkit.datamodel.TskData.TSK_DB_FILES_TYPE_ENUM;
|
||||
|
||||
public class ReportHTML implements TableReportModule {
|
||||
@@ -91,7 +90,7 @@ public class ReportHTML implements TableReportModule {
|
||||
currentCase = Case.getCurrentCase();
|
||||
skCase = currentCase.getSleuthkitCase();
|
||||
|
||||
dataTypes = new TreeMap<String, Integer>();
|
||||
dataTypes = new TreeMap<>();
|
||||
|
||||
path = "";
|
||||
currentDataType = "";
|
||||
@@ -129,10 +128,10 @@ public class ReportHTML implements TableReportModule {
|
||||
{
|
||||
String iconFilePath;
|
||||
String iconFileName;
|
||||
InputStream in = null;
|
||||
InputStream in;
|
||||
OutputStream output = null;
|
||||
|
||||
logger.log(Level.INFO, "useDataTypeIcon: dataType = " + dataType);
|
||||
logger.log(Level.INFO, "useDataTypeIcon: dataType = {0}", dataType);
|
||||
|
||||
// find the artifact with matching display name
|
||||
BlackboardArtifact.ARTIFACT_TYPE artifactType = null;
|
||||
@@ -296,39 +295,6 @@ public class ReportHTML implements TableReportModule {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a new HTML page for the given data type. Update the output stream to this page,
|
||||
* and setup the web page header.
|
||||
* @param title title of the data type
|
||||
*/
|
||||
@Override
|
||||
public void startDataType(String title) {
|
||||
String fTitle = dataTypeToFileName(title);
|
||||
// Make a new out for this page
|
||||
try {
|
||||
//escape out slashes tha that appear in title
|
||||
|
||||
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path + fTitle + getExtension()), "UTF-8"));
|
||||
} catch (FileNotFoundException ex) {
|
||||
logger.log(Level.SEVERE, "File not found: {0}", ex);
|
||||
} catch (UnsupportedEncodingException ex) {
|
||||
logger.log(Level.SEVERE, "Unrecognized encoding");
|
||||
}
|
||||
|
||||
// Write the beginnings of a page
|
||||
// Like <html>, header, title, any content divs
|
||||
try {
|
||||
StringBuilder page = new StringBuilder();
|
||||
page.append("<html>\n<head>\n\t<title>").append(title).append("</title>\n\t<link rel=\"stylesheet\" type=\"text/css\" href=\"index.css\" />\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n</head>\n<body>\n");
|
||||
page.append("<div id=\"header\">").append(title).append("</div>\n<div id=\"content\">\n");
|
||||
out.write(page.toString());
|
||||
currentDataType = title;
|
||||
rowCount = 0;
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.SEVERE, "Failed to write page head: {0}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a new HTML page for the given data type. Update the output stream to this page,
|
||||
@@ -338,7 +304,8 @@ public class ReportHTML implements TableReportModule {
|
||||
* @param name Name of the data type
|
||||
* @param comment Comment on the data type, may be the empty string
|
||||
*/
|
||||
public void startDataType(String name, String comment) {
|
||||
@Override
|
||||
public void startDataType(String name, String description) {
|
||||
String title = dataTypeToFileName(name);
|
||||
try {
|
||||
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path + title + getExtension()), "UTF-8"));
|
||||
@@ -352,9 +319,9 @@ public class ReportHTML implements TableReportModule {
|
||||
StringBuilder page = new StringBuilder();
|
||||
page.append("<html>\n<head>\n\t<title>").append(name).append("</title>\n\t<link rel=\"stylesheet\" type=\"text/css\" href=\"index.css\" />\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n</head>\n<body>\n");
|
||||
page.append("<div id=\"header\">").append(name).append("</div>\n<div id=\"content\">\n");
|
||||
if (!comment.isEmpty()) {
|
||||
if (!description.isEmpty()) {
|
||||
page.append("<p><strong>");
|
||||
page.append(comment);
|
||||
page.append(description);
|
||||
page.append("</string></p>\n");
|
||||
}
|
||||
out.write(page.toString());
|
||||
@@ -477,17 +444,17 @@ public class ReportHTML implements TableReportModule {
|
||||
* @param columnHeaders column headers
|
||||
* @param sourceArtifact source blackboard artifact for the table data
|
||||
*/
|
||||
public void startTable(List<String> columnHeaders, ARTIFACT_TYPE artifactType) {
|
||||
public void startContentTagsTable(List<String> columnHeaders) {
|
||||
StringBuilder htmlOutput = new StringBuilder();
|
||||
htmlOutput.append("<table>\n<thead>\n\t<tr>\n");
|
||||
|
||||
// Add the specified columns.
|
||||
for(String columnHeader : columnHeaders) {
|
||||
htmlOutput.append("\t\t<th>").append(columnHeader).append("</th>\n");
|
||||
}
|
||||
|
||||
// For file tag artifacts, add a column for a hyperlink to a local copy of the tagged file.
|
||||
if (artifactType.equals(ARTIFACT_TYPE.TSK_TAG_FILE)) {
|
||||
htmlOutput.append("\t\t<th></th>\n");
|
||||
}
|
||||
// Add a column for a hyperlink to a local copy of the tagged content.
|
||||
htmlOutput.append("\t\t<th></th>\n");
|
||||
|
||||
htmlOutput.append("\t</tr>\n</thead>\n");
|
||||
|
||||
@@ -527,20 +494,75 @@ public class ReportHTML implements TableReportModule {
|
||||
try {
|
||||
out.write(builder.toString());
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.SEVERE, "Failed to write row to out.");
|
||||
logger.log(Level.SEVERE, "Failed to write row to out.", ex);
|
||||
} catch (NullPointerException ex) {
|
||||
logger.log(Level.SEVERE, "Output writer is null. Page was not initialized before writing.");
|
||||
logger.log(Level.SEVERE, "Output writer is null. Page was not initialized before writing.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a row to the current table.
|
||||
* Saves a local copy of a tagged file and adds a row with a hyper link to
|
||||
* the file.
|
||||
*
|
||||
* @param row values for each cell in the row
|
||||
* @param sourceArtifact source blackboard artifact for the table data
|
||||
* @param row Values for each data cell in the row.
|
||||
* @param contentTag A content tag to use to make the hyper link.
|
||||
*/
|
||||
public void addRow(List<String> row, BlackboardArtifact sourceArtifact) {
|
||||
addRowDataForSourceArtifact(row, sourceArtifact);
|
||||
public void addRowWithTaggedContentHyperlink(List<String> row, ContentTag contentTag) {
|
||||
// Only handling AbstractFiles at present.
|
||||
AbstractFile file;
|
||||
if (contentTag.getContent() instanceof AbstractFile) {
|
||||
file = (AbstractFile)contentTag.getContent();
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't make a local copy of the file if it is a directory or unallocated space.
|
||||
if (file.isDir() ||
|
||||
file.getType() == TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS ||
|
||||
file.getType() == TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS) {
|
||||
row.add("");
|
||||
return;
|
||||
}
|
||||
|
||||
// Make a folder for the local file with the same name as the tag.
|
||||
StringBuilder localFilePath = new StringBuilder();
|
||||
localFilePath.append(path);
|
||||
localFilePath.append(contentTag.getName().getDisplayName());
|
||||
File localFileFolder = new File(localFilePath.toString());
|
||||
if (!localFileFolder.exists()) {
|
||||
localFileFolder.mkdirs();
|
||||
}
|
||||
|
||||
// Construct a file name for the local file that incorporates the file id to ensure uniqueness.
|
||||
String fileName = file.getName();
|
||||
String objectIdSuffix = "_" + file.getId();
|
||||
int lastDotIndex = fileName.lastIndexOf(".");
|
||||
if (lastDotIndex != -1 && lastDotIndex != 0) {
|
||||
// The file name has a conventional extension. Insert the object id before the '.' of the extension.
|
||||
fileName = fileName.substring(0, lastDotIndex) + objectIdSuffix + fileName.substring(lastDotIndex, fileName.length());
|
||||
}
|
||||
else {
|
||||
// The file has no extension or the only '.' in the file is an initial '.', as in a hidden file.
|
||||
// Add the object id to the end of the file name.
|
||||
fileName += objectIdSuffix;
|
||||
}
|
||||
localFilePath.append(File.separator);
|
||||
localFilePath.append(fileName);
|
||||
|
||||
// If the local file doesn't already exist, create it now.
|
||||
// The existence check is necessary because it is possible to apply multiple tags with the same name to a file.
|
||||
File localFile = new File(localFilePath.toString());
|
||||
if (!localFile.exists()) {
|
||||
ExtractFscContentVisitor.extract(file, localFile, null, null);
|
||||
}
|
||||
|
||||
// Add the hyperlink to the row. A column header for it was created in startTable().
|
||||
StringBuilder localFileLink = new StringBuilder();
|
||||
localFileLink.append("<a href=\"file:///");
|
||||
localFileLink.append(localFilePath.toString());
|
||||
localFileLink.append("\">View File</a>");
|
||||
row.add(localFileLink.toString());
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("\t<tr>\n");
|
||||
@@ -561,90 +583,6 @@ public class ReportHTML implements TableReportModule {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add cells particular to a type of artifact associated with the row. Assumes that the overload of startTable() that takes an artifact type was called.
|
||||
*
|
||||
* @param row The row.
|
||||
* @param sourceArtifact The artifact associated with the row.
|
||||
*/
|
||||
private void addRowDataForSourceArtifact(List<String> row, BlackboardArtifact sourceArtifact) {
|
||||
// int artifactTypeID = sourceArtifact.getArtifactTypeID();
|
||||
// BlackboardArtifact.ARTIFACT_TYPE type = BlackboardArtifact.ARTIFACT_TYPE.fromID(artifactTypeID);
|
||||
// switch (type) {
|
||||
// case TSK_TAG_FILE:
|
||||
// addRowDataForFileTagArtifact(row, sourceArtifact);
|
||||
// break;
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves a local copy of a tagged file and adds a hyper link to the file to the row.
|
||||
*
|
||||
* @param row The row.
|
||||
* @param sourceArtifact The artifact associated with the row.
|
||||
*/
|
||||
private void addRowDataForFileTagArtifact(List<String> row, BlackboardArtifact sourceArtifact) {
|
||||
// try {
|
||||
// AbstractFile file = Case.getCurrentCase().getSleuthkitCase().getAbstractFileById(sourceArtifact.getObjectID());
|
||||
//
|
||||
// // Don't make a local copy of the file if it is a directory or unallocated space.
|
||||
// if (file.isDir() ||
|
||||
// file.getType() == TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS ||
|
||||
// file.getType() == TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS) {
|
||||
// row.add("");
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// // Make a folder for the local file with the same name as the tag.
|
||||
// StringBuilder localFilePath = new StringBuilder();
|
||||
// localFilePath.append(path);
|
||||
// HashSet<String> tagNames = Tags.getUniqueTagNamesForArtifact(sourceArtifact);
|
||||
// if (!tagNames.isEmpty()) {
|
||||
// localFilePath.append(tagNames.iterator().next());
|
||||
// }
|
||||
// File localFileFolder = new File(localFilePath.toString());
|
||||
// if (!localFileFolder.exists()) {
|
||||
// localFileFolder.mkdirs();
|
||||
// }
|
||||
//
|
||||
// // Construct a file name for the local file that incorporates the corresponding object id to ensure uniqueness.
|
||||
// String fileName = file.getName();
|
||||
// String objectIdSuffix = "_" + sourceArtifact.getObjectID();
|
||||
// int lastDotIndex = fileName.lastIndexOf(".");
|
||||
// if (lastDotIndex != -1 && lastDotIndex != 0) {
|
||||
// // The file name has a conventional extension. Insert the object id before the '.' of the extension.
|
||||
// fileName = fileName.substring(0, lastDotIndex) + objectIdSuffix + fileName.substring(lastDotIndex, fileName.length());
|
||||
// }
|
||||
// else {
|
||||
// // The file has no extension or the only '.' in the file is an initial '.', as in a hidden file.
|
||||
// // Add the object id to the end of the file name.
|
||||
// fileName += objectIdSuffix;
|
||||
// }
|
||||
// localFilePath.append(File.separator);
|
||||
// localFilePath.append(fileName);
|
||||
//
|
||||
// // If the local file doesn't already exist, create it now.
|
||||
// // The existence check is necessary because it is possible to apply multiple tags with the same name to a file.
|
||||
// File localFile = new File(localFilePath.toString());
|
||||
// if (!localFile.exists()) {
|
||||
// ExtractFscContentVisitor.extract(file, localFile, null, null);
|
||||
// }
|
||||
//
|
||||
// // Add the hyperlink to the row. A column header for it was created in startTable().
|
||||
// StringBuilder localFileLink = new StringBuilder();
|
||||
// localFileLink.append("<a href=\"file:///");
|
||||
// localFileLink.append(localFilePath.toString());
|
||||
// localFileLink.append("\">View File</a>");
|
||||
// row.add(localFileLink.toString());
|
||||
// }
|
||||
// catch (TskCoreException ex) {
|
||||
// logger.log(Level.WARNING, "Failed to get AbstractFile by ID.", ex);
|
||||
// row.add("");
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a String date for the long date given.
|
||||
* @param date date as a long
|
||||
@@ -704,11 +642,11 @@ public class ReportHTML implements TableReportModule {
|
||||
"table tr:nth-child(even) td {background: #f3f3f3;}";
|
||||
cssOut.write(css);
|
||||
} catch (FileNotFoundException ex) {
|
||||
logger.log(Level.SEVERE, "Could not find index.css file to write to.");
|
||||
logger.log(Level.SEVERE, "Could not find index.css file to write to.", ex);
|
||||
} catch (UnsupportedEncodingException ex) {
|
||||
logger.log(Level.SEVERE, "Did not recognize encoding when writing index.css.");
|
||||
logger.log(Level.SEVERE, "Did not recognize encoding when writing index.css.", ex);
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.SEVERE, "Error creating Writer for index.css.");
|
||||
logger.log(Level.SEVERE, "Error creating Writer for index.css.", ex);
|
||||
} finally {
|
||||
try {
|
||||
if(cssOut != null) {
|
||||
|
||||
@@ -71,7 +71,7 @@ public final class ReportWizardAction extends CallableSystemAction implements P
|
||||
ReportGenerator generator = new ReportGenerator((Map<TableReportModule, Boolean>)wiz.getProperty("tableModuleStates"),
|
||||
(Map<GeneralReportModule, Boolean>)wiz.getProperty("generalModuleStates"),
|
||||
(Map<FileReportModule, Boolean>)wiz.getProperty("fileModuleStates"));
|
||||
generator.generateArtifactTableReports((Map<ARTIFACT_TYPE, Boolean>)wiz.getProperty("artifactStates"), (Map<String, Boolean>)wiz.getProperty("tagStates"));
|
||||
generator.generateBlackboardArtifactsReports((Map<ARTIFACT_TYPE, Boolean>)wiz.getProperty("artifactStates"), (Map<String, Boolean>)wiz.getProperty("tagStates"));
|
||||
generator.generateFileListReports((Map<FileReportDataTypes, Boolean>)wiz.getProperty("fileReportOptions"));
|
||||
generator.generateGeneralReports();
|
||||
generator.displayProgressPanels();
|
||||
|
||||
@@ -51,8 +51,9 @@ public interface TableReportModule extends ReportModule {
|
||||
* It is up to the report how the differentiation is shown.
|
||||
*
|
||||
* @param title String name of the data type
|
||||
* @param description RJCTODO: fix this header comment
|
||||
*/
|
||||
public void startDataType(String title);
|
||||
public void startDataType(String title, String description);
|
||||
|
||||
/**
|
||||
* End the current data type and prepare for either the end of the report
|
||||
|
||||
Reference in New Issue
Block a user