19 package org.sleuthkit.autopsy.centralrepository.contentviewer;
 
   21 import java.awt.Component;
 
   22 import java.awt.event.ActionEvent;
 
   23 import java.awt.event.ActionListener;
 
   24 import java.awt.event.ComponentAdapter;
 
   25 import java.awt.event.ComponentEvent;
 
   26 import java.io.BufferedWriter;
 
   28 import java.io.IOException;
 
   29 import java.nio.file.Files;
 
   30 import java.text.DateFormat;
 
   31 import java.text.ParseException;
 
   32 import java.text.SimpleDateFormat;
 
   33 import java.util.ArrayList;
 
   34 import java.util.Calendar;
 
   35 import java.util.Collection;
 
   36 import java.util.HashMap;
 
   37 import java.util.HashSet;
 
   38 import java.util.List;
 
   39 import java.util.Locale;
 
   41 import java.util.Objects;
 
   43 import java.util.logging.Level;
 
   45 import javax.swing.JFileChooser;
 
   46 import javax.swing.JMenuItem;
 
   47 import javax.swing.JOptionPane;
 
   48 import static javax.swing.JOptionPane.DEFAULT_OPTION;
 
   49 import static javax.swing.JOptionPane.PLAIN_MESSAGE;
 
   50 import static javax.swing.JOptionPane.ERROR_MESSAGE;
 
   51 import javax.swing.JPanel;
 
   52 import javax.swing.filechooser.FileNameExtensionFilter;
 
   53 import javax.swing.table.TableModel;
 
   54 import javax.swing.table.TableRowSorter;
 
   55 import org.joda.time.DateTimeZone;
 
   56 import org.joda.time.LocalDateTime;
 
   57 import org.openide.nodes.Node;
 
   58 import org.openide.util.NbBundle.Messages;
 
   59 import org.openide.util.lookup.ServiceProvider;
 
   83 @SuppressWarnings(
"PMD.SingularField") 
 
   84 @ServiceProvider(service = DataContentViewer.class, position = 9)
 
   85 @Messages({
"DataContentViewerOtherCases.title=Other Occurrences",
 
   86     "DataContentViewerOtherCases.toolTip=Displays instances of the selected file/artifact from other occurrences.",
 
   87     "DataContentViewerOtherCases.table.noArtifacts=Item has no attributes with which to search.",
 
   88     "DataContentViewerOtherCases.table.noResultsFound=No results found."})
 
   91     private static final long serialVersionUID = -1L;
 
   92     private static final String UUID_PLACEHOLDER_STRING = 
"NoCorrelationAttributeInstance";
 
   94     private static final CorrelationCaseWrapper NO_ARTIFACTS_CASE = 
new CorrelationCaseWrapper(Bundle.DataContentViewerOtherCases_table_noArtifacts());
 
   95     private static final CorrelationCaseWrapper NO_RESULTS_CASE = 
new CorrelationCaseWrapper(Bundle.DataContentViewerOtherCases_table_noResultsFound());
 
  101     private String dataSourceName = 
"";  
 
  102     private String deviceId = 
""; 
 
  114         this.dataSourcesTableModel = 
new OtherOccurrencesDataSourcesTableModel();
 
  115         this.correlationAttributes = 
new ArrayList<>();
 
  116         occurrencePanel = 
new OccurrencePanel();
 
  118         customizeComponents();
 
  120         detailsPanelScrollPane.addComponentListener(
new ComponentAdapter() {
 
  122             public void componentResized(ComponentEvent componentEvent) {
 
  124                 occurrencePanel.setPreferredSize(
new java.awt.Dimension(detailsPanelScrollPane.getPreferredSize().width, occurrencePanel.getPreferredSize().height));
 
  125                 detailsPanelScrollPane.setViewportView(occurrencePanel);
 
  137     static String getPlaceholderUUID() {
 
  138         return UUID_PLACEHOLDER_STRING;
 
  142         ActionListener actList = (ActionEvent e) -> {
 
  143             JMenuItem jmi = (JMenuItem) e.getSource();
 
  144             if (jmi.equals(showCaseDetailsMenuItem)) {
 
  145                 showCaseDetails(filesTable.getSelectedRow());
 
  146             } 
else if (jmi.equals(exportToCSVMenuItem)) {
 
  150                     LOGGER.log(Level.SEVERE, 
"Exception while getting open case.", ex); 
 
  152             } 
else if (jmi.equals(showCommonalityMenuItem)) {
 
  153                 showCommonalityDetails();
 
  157         exportToCSVMenuItem.addActionListener(actList);
 
  158         showCaseDetailsMenuItem.addActionListener(actList);
 
  159         showCommonalityMenuItem.addActionListener(actList);
 
  162         TableRowSorter<TableModel> sorter = 
new TableRowSorter<>(filesTable.getModel());
 
  163         filesTable.setRowSorter(sorter);
 
  164         casesTable.getSelectionModel().addListSelectionListener((e) -> {
 
  166                 updateOnCaseSelection();
 
  169         dataSourcesTable.getSelectionModel().addListSelectionListener((e) -> {
 
  171                 updateOnDataSourceSelection();
 
  176         filesTable.getSelectionModel().addListSelectionListener((e) -> {
 
  178                 occurrencePanel = 
new OccurrencePanel();
 
  179                 updateOnFileSelection();
 
  183         casesTable.getRowSorter().toggleSortOrder(0);
 
  184         dataSourcesTable.getRowSorter().toggleSortOrder(0);
 
  185         filesTable.getRowSorter().toggleSortOrder(0);
 
  188     @Messages({
"DataContentViewerOtherCases.correlatedArtifacts.isEmpty=There are no files or artifacts to correlate.",
 
  189         "# {0} - commonality percentage",
 
  190         "# {1} - correlation type",
 
  191         "# {2} - correlation value",
 
  192         "DataContentViewerOtherCases.correlatedArtifacts.byType={0}% of data sources have {2} (type: {1})\n",
 
  193         "DataContentViewerOtherCases.correlatedArtifacts.title=Attribute Frequency",
 
  194         "DataContentViewerOtherCases.correlatedArtifacts.failed=Failed to get frequency details."})
 
  200         if (correlationAttributes.isEmpty()) {
 
  201             JOptionPane.showConfirmDialog(showCommonalityMenuItem,
 
  202                     Bundle.DataContentViewerOtherCases_correlatedArtifacts_isEmpty(),
 
  203                     Bundle.DataContentViewerOtherCases_correlatedArtifacts_title(),
 
  204                     DEFAULT_OPTION, PLAIN_MESSAGE);
 
  206             StringBuilder msg = 
new StringBuilder(correlationAttributes.size());
 
  213                         msg.append(Bundle.DataContentViewerOtherCases_correlatedArtifacts_byType(percentage,
 
  214                                 eamArtifact.getCorrelationType().getDisplayName(),
 
  215                                 eamArtifact.getCorrelationValue()));
 
  217                         LOGGER.log(Level.WARNING, String.format(
"Error getting commonality details for artifact with ID: %s.", eamArtifact.getID()), ex);
 
  220                 JOptionPane.showConfirmDialog(showCommonalityMenuItem,
 
  222                         Bundle.DataContentViewerOtherCases_correlatedArtifacts_title(),
 
  223                         DEFAULT_OPTION, PLAIN_MESSAGE);
 
  225                 LOGGER.log(Level.SEVERE, 
"Error getting commonality details.", ex);
 
  226                 JOptionPane.showConfirmDialog(showCommonalityMenuItem,
 
  227                         Bundle.DataContentViewerOtherCases_correlatedArtifacts_failed(),
 
  228                         Bundle.DataContentViewerOtherCases_correlatedArtifacts_title(),
 
  229                         DEFAULT_OPTION, ERROR_MESSAGE);
 
  234     @Messages({
"DataContentViewerOtherCases.caseDetailsDialog.notSelected=No Row Selected",
 
  235         "DataContentViewerOtherCases.caseDetailsDialog.noDetails=No details for this case.",
 
  236         "DataContentViewerOtherCases.caseDetailsDialog.noDetailsReference=No case details for Global reference properties.",
 
  237         "DataContentViewerOtherCases.caseDetailsDialog.noCaseNameError=Error",
 
  238         "DataContentViewerOtherCases.noOpenCase.errMsg=No open case available."})
 
  240         String caseDisplayName = Bundle.DataContentViewerOtherCases_caseDetailsDialog_noCaseNameError();
 
  241         String details = Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetails();
 
  243             if (-1 != selectedRowViewIdx) {
 
  245                 int selectedRowModelIdx = filesTable.convertRowIndexToModel(selectedRowViewIdx);
 
  246                 List<OtherOccurrenceNodeData> rowList = filesTableModel.getListOfNodesForFile(selectedRowModelIdx);
 
  247                 if (!rowList.isEmpty()) {
 
  248                     if (rowList.get(0) instanceof OtherOccurrenceNodeInstanceData) {
 
  249                         CorrelationCase eamCasePartial = ((OtherOccurrenceNodeInstanceData) rowList.get(0)).getCorrelationAttributeInstance().getCorrelationCase();
 
  253                         if (eamCase != null) {
 
  256                             details = Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetails();
 
  259                         details = Bundle.DataContentViewerOtherCases_caseDetailsDialog_notSelected();
 
  262                     details = Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetailsReference();
 
  266             LOGGER.log(Level.SEVERE, 
"Error loading case details", ex);
 
  268             JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
 
  271                     DEFAULT_OPTION, PLAIN_MESSAGE);
 
  277             Calendar now = Calendar.getInstance();
 
  278             String fileName = String.format(
"%1$tY%1$tm%1$te%1$tI%1$tM%1$tS_other_data_sources.csv", now);
 
  280             CSVFileChooser.setSelectedFile(
new File(fileName));
 
  281             CSVFileChooser.setFileFilter(
new FileNameExtensionFilter(
"csv file", 
"csv"));
 
  283             int returnVal = CSVFileChooser.showSaveDialog(filesTable);
 
  284             if (returnVal == JFileChooser.APPROVE_OPTION) {
 
  286                 File selectedFile = CSVFileChooser.getSelectedFile();
 
  287                 if (!selectedFile.getName().endsWith(
".csv")) { 
 
  288                     selectedFile = 
new File(selectedFile.toString() + 
".csv"); 
 
  290                 writeOtherOccurrencesToFileAsCSV(selectedFile);
 
  296         "DataContentViewerOtherCasesModel.csvHeader.case=Case",
 
  297         "DataContentViewerOtherCasesModel.csvHeader.device=Device",
 
  298         "DataContentViewerOtherCasesModel.csvHeader.dataSource=Data Source",
 
  299         "DataContentViewerOtherCasesModel.csvHeader.attribute=Matched Attribute",
 
  300         "DataContentViewerOtherCasesModel.csvHeader.value=Attribute Value",
 
  301         "DataContentViewerOtherCasesModel.csvHeader.known=Known",
 
  302         "DataContentViewerOtherCasesModel.csvHeader.path=Path",
 
  303         "DataContentViewerOtherCasesModel.csvHeader.comment=Comment" 
  309         try (BufferedWriter writer = Files.newBufferedWriter(destFile.toPath())) {
 
  311             StringBuilder headers = 
new StringBuilder(
"\"");
 
  312             headers.append(Bundle.DataContentViewerOtherCasesModel_csvHeader_case())
 
  313                     .append(OtherOccurrenceNodeInstanceData.getCsvItemSeparator()).append(Bundle.DataContentViewerOtherCasesModel_csvHeader_dataSource())
 
  314                     .append(OtherOccurrenceNodeInstanceData.getCsvItemSeparator()).append(Bundle.DataContentViewerOtherCasesModel_csvHeader_attribute())
 
  315                     .append(OtherOccurrenceNodeInstanceData.getCsvItemSeparator()).append(Bundle.DataContentViewerOtherCasesModel_csvHeader_value())
 
  316                     .append(OtherOccurrenceNodeInstanceData.getCsvItemSeparator()).append(Bundle.DataContentViewerOtherCasesModel_csvHeader_known())
 
  317                     .append(OtherOccurrenceNodeInstanceData.getCsvItemSeparator()).append(Bundle.DataContentViewerOtherCasesModel_csvHeader_path())
 
  318                     .append(OtherOccurrenceNodeInstanceData.getCsvItemSeparator()).append(Bundle.DataContentViewerOtherCasesModel_csvHeader_comment())
 
  319                     .append(
'"').append(System.getProperty(
"line.separator"));
 
  320             writer.write(headers.toString());
 
  323                 Map<UniquePathKey, OtherOccurrenceNodeInstanceData> correlatedNodeDataMap = 
new HashMap<>(0);
 
  325                 correlatedNodeDataMap.putAll(getCorrelatedInstances(corAttr, dataSourceName, deviceId));
 
  326                 for (OtherOccurrenceNodeInstanceData nodeData : correlatedNodeDataMap.values()) {
 
  327                     writer.write(nodeData.toCsvString());
 
  330         } 
catch (IOException ex) {
 
  331             LOGGER.log(Level.SEVERE, 
"Error writing selected rows to CSV.", ex);
 
  340         casesTableModel.clearTable();
 
  341         dataSourcesTableModel.clearTable();
 
  342         filesTableModel.clearTable();
 
  343         correlationAttributes.clear();
 
  344         earliestCaseDate.setText(Bundle.DataContentViewerOtherCases_earliestCaseNotAvailable());
 
  345         foundInLabel.setText(
"");
 
  347         occurrencePanel = 
new OccurrencePanel();
 
  348         occurrencePanel.getPreferredSize();
 
  349         detailsPanelScrollPane.setViewportView(occurrencePanel);
 
  354         return Bundle.DataContentViewerOtherCases_title();
 
  359         return Bundle.DataContentViewerOtherCases_toolTip();
 
  390     private BlackboardArtifact
 
  392         BlackboardArtifactTag nodeBbArtifactTag = node.getLookup().lookup(BlackboardArtifactTag.class
 
  394         BlackboardArtifact nodeBbArtifact = node.getLookup().lookup(BlackboardArtifact.class
 
  397         if (nodeBbArtifactTag != null) {
 
  398             return nodeBbArtifactTag.getArtifact();
 
  399         } 
else if (nodeBbArtifact != null) {
 
  400             return nodeBbArtifact;
 
  415         BlackboardArtifactTag nodeBbArtifactTag = node.getLookup().lookup(BlackboardArtifactTag.class
 
  417         ContentTag nodeContentTag = node.getLookup().lookup(ContentTag.class
 
  419         BlackboardArtifact nodeBbArtifact = node.getLookup().lookup(BlackboardArtifact.class
 
  421         AbstractFile nodeAbstractFile = node.getLookup().lookup(AbstractFile.class
 
  424         if (nodeBbArtifactTag != null) {
 
  425             Content content = nodeBbArtifactTag.getContent();
 
  426             if (content instanceof AbstractFile) {
 
  427                 return (AbstractFile) content;
 
  429         } 
else if (nodeContentTag != null) {
 
  430             Content content = nodeContentTag.getContent();
 
  431             if (content instanceof AbstractFile) {
 
  432                 return (AbstractFile) content;
 
  434         } 
else if (nodeBbArtifact != null) {
 
  437                 content = nodeBbArtifact.getSleuthkitCase().getContentById(nodeBbArtifact.getObjectID());
 
  438             } 
catch (TskCoreException ex) {
 
  439                 LOGGER.log(Level.SEVERE, 
"Error retrieving blackboard artifact", ex); 
 
  443             if (content instanceof AbstractFile) {
 
  444                 return (AbstractFile) content;
 
  446         } 
else if (nodeAbstractFile != null) {
 
  447             return nodeAbstractFile;
 
  462         Collection<CorrelationAttributeInstance> ret = 
new ArrayList<>();
 
  465         BlackboardArtifact bbArtifact = getBlackboardArtifactFromNode(node);
 
  475                 String md5 = this.file.getMd5Hash();
 
  476                 if (md5 != null && !md5.isEmpty() && null != artifactTypes && !artifactTypes.isEmpty()) {
 
  486                                         file.getParentPath() + file.
getName(),
 
  491                                 LOGGER.log(Level.INFO, String.format(
"Unable to check create CorrelationAttribtueInstance for value %s and type %s.", md5, aType.toString()), ex);
 
  498                 LOGGER.log(Level.SEVERE, 
"Error connecting to DB", ex); 
 
  501         } 
else if (this.file != null && this.file.getSize() > 0) {
 
  502             String md5 = this.file.getMd5Hash();
 
  503             if (md5 != null && !md5.isEmpty()) {
 
  514                     LOGGER.log(Level.SEVERE, 
"Error connecting to DB", ex); 
 
  516                     LOGGER.log(Level.INFO, String.format(
"Unable to create CorrelationAttributeInstance for value %s", md5), ex); 
 
  524     @Messages({
"DataContentViewerOtherCases.earliestCaseNotAvailable= Not Enabled."})
 
  530         String dateStringDisplay = Bundle.DataContentViewerOtherCases_earliestCaseNotAvailable();
 
  533             LocalDateTime earliestDate = LocalDateTime.now(DateTimeZone.UTC);
 
  534             DateFormat datetimeFormat = 
new SimpleDateFormat(
"yyyy/MM/dd HH:mm:ss", Locale.US);
 
  537                 List<CorrelationCase> cases = dbManager.
getCases();
 
  539                     LocalDateTime caseDate = LocalDateTime.fromDateFields(datetimeFormat.parse(aCase.getCreationDate()));
 
  541                     if (caseDate.isBefore(earliestDate)) {
 
  542                         earliestDate = caseDate;
 
  543                         dateStringDisplay = aCase.getCreationDate();
 
  549                 LOGGER.log(Level.SEVERE, 
"Error getting list of cases from database.", ex); 
 
  550             } 
catch (ParseException ex) {
 
  551                 LOGGER.log(Level.SEVERE, 
"Error parsing date of cases from database.", ex); 
 
  555         earliestCaseDate.setText(dateStringDisplay);
 
  574             String caseUUID = openCase.
getName();
 
  575             HashMap<UniquePathKey, OtherOccurrenceNodeInstanceData> nodeDataMap = 
new HashMap<>();
 
  588                     if (!artifactInstance.getCorrelationCase().getCaseUUID().equals(caseUUID)
 
  589                             || !artifactInstance.getCorrelationDataSource().getName().equals(dataSourceName)
 
  590                             || !artifactInstance.getCorrelationDataSource().getDeviceID().equals(deviceId)
 
  591                             || !artifactInstance.getFilePath().equalsIgnoreCase(file.getParentPath() + file.getName())) {
 
  595                         nodeDataMap.put(uniquePathKey, newNode);
 
  600                 List<AbstractFile> caseDbFiles = getCaseDbMatches(corAttr, openCase);
 
  602                 for (AbstractFile caseDbFile : caseDbFiles) {
 
  603                     addOrUpdateNodeData(openCase, nodeDataMap, caseDbFile);
 
  608             LOGGER.log(Level.SEVERE, 
"Error getting artifact instances from database.", ex); 
 
  610             LOGGER.log(Level.INFO, 
"Error getting artifact instances from database.", ex); 
 
  612             LOGGER.log(Level.SEVERE, 
"Exception while getting open case.", ex); 
 
  613         } 
catch (TskCoreException ex) {
 
  616             LOGGER.log(Level.SEVERE, 
"Exception while querying open case.", ex); 
 
  619         return new HashMap<>(0);
 
  636         String md5 = corAttr.getCorrelationValue();
 
  637         SleuthkitCase tsk = openCase.getSleuthkitCase();
 
  638         List<AbstractFile> matches = tsk.findAllFilesWhere(String.format(
"md5 = '%s'", 
new Object[]{md5}));
 
  640         List<AbstractFile> caseDbArtifactInstances = 
new ArrayList<>();
 
  641         for (AbstractFile fileMatch : matches) {
 
  642             if (this.file.equals(fileMatch)) {
 
  645             caseDbArtifactInstances.add(fileMatch);
 
  647         return caseDbArtifactInstances;
 
  663         OtherOccurrenceNodeInstanceData newNode = 
new OtherOccurrenceNodeInstanceData(newFile, autopsyCase);
 
  667         if (newNode.getKnown() != TskData.FileKnown.BAD) {
 
  668             List<ContentTag> fileMatchTags = autopsyCase.getServices().getTagsManager().getContentTagsByContent(newFile);
 
  669             for (ContentTag tag : fileMatchTags) {
 
  670                 TskData.FileKnown tagKnownStatus = tag.getName().getKnownStatus();
 
  671                 if (tagKnownStatus.equals(TskData.FileKnown.BAD)) {
 
  672                     newNode.updateKnown(TskData.FileKnown.BAD);
 
  684         if (nodeDataMap.containsKey(uniquePathKey)) {
 
  685             if (newNode.getKnown() == TskData.FileKnown.BAD) {
 
  686                 OtherOccurrenceNodeInstanceData prevInstance = nodeDataMap.get(uniquePathKey);
 
  687                 prevInstance.updateKnown(newNode.getKnown());
 
  690             nodeDataMap.put(uniquePathKey, newNode);
 
  701         this.file = this.getAbstractFileFromNode(node);
 
  703             return !getCorrelationAttributesFromNode(node).isEmpty();
 
  705             return this.file != null
 
  706                     && this.file.getSize() > 0
 
  707                     && ((this.file.getMd5Hash() != null) && (!this.file.getMd5Hash().isEmpty()));
 
  719         this.file = this.getAbstractFileFromNode(node);
 
  731         "DataContentViewerOtherCases.dataSources.header.text=Data Source Name",
 
  732         "DataContentViewerOtherCases.foundIn.text=Found %d instances in %d cases and %d data sources." 
  736             if (this.file != null) {
 
  737                 Content dataSource = this.file.getDataSource();
 
  738                 dataSourceName = dataSource.getName();
 
  741         } 
catch (TskException | NoCurrentCaseException ex) {
 
  747         correlationAttributes.addAll(getCorrelationAttributesFromNode(node));
 
  748         Map<String, CorrelationCase> caseNames = 
new HashMap<>();
 
  750         Set<String> dataSources = 
new HashSet<>();
 
  752             Map<UniquePathKey, OtherOccurrenceNodeInstanceData> correlatedNodeDataMap = 
new HashMap<>(0);
 
  755             correlatedNodeDataMap.putAll(getCorrelatedInstances(corAttr, dataSourceName, deviceId));
 
  756             for (OtherOccurrenceNodeInstanceData nodeData : correlatedNodeDataMap.values()) {
 
  757                 if (nodeData.isCentralRepoNode()) {
 
  759                         dataSources.add(makeDataSourceString(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID(), nodeData.getDeviceID(), nodeData.getDataSourceName()));
 
  760                         caseNames.put(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID(), nodeData.getCorrelationAttributeInstance().getCorrelationCase());
 
  762                         LOGGER.log(Level.WARNING, 
"Unable to get correlation case for displaying other occurrence for case: " + nodeData.getCaseName(), ex);
 
  768                     } 
catch (NoCurrentCaseException ex) {
 
  769                         LOGGER.log(Level.WARNING, 
"No current case open for other occurrences", ex);
 
  776             casesTableModel.addCorrelationCase(
new CorrelationCaseWrapper(corCase));
 
  779         if (correlationAttributes.isEmpty()) {
 
  780             casesTableModel.addCorrelationCase(NO_ARTIFACTS_CASE);
 
  781         } 
else if (caseCount == 0) {
 
  782             casesTableModel.addCorrelationCase(NO_RESULTS_CASE);
 
  784         setEarliestCaseDate();
 
  785         foundInLabel.setText(String.format(Bundle.DataContentViewerOtherCases_foundIn_text(), totalCount, caseCount, dataSources.size()));
 
  787             casesTable.setRowSelectionInterval(0, 0);
 
  796         return caseUUID + deviceId + dataSourceName;
 
  803         int[] selectedCaseIndexes = casesTable.getSelectedRows();
 
  804         dataSourcesTableModel.clearTable();
 
  805         filesTableModel.clearTable();
 
  807         if (selectedCaseIndexes.length == 0) {
 
  809             occurrencePanel = 
new OccurrencePanel();
 
  810             occurrencePanel.getPreferredSize();
 
  811             detailsPanelScrollPane.setViewportView(occurrencePanel);
 
  813             String currentCaseName;
 
  816             } 
catch (NoCurrentCaseException ex) {
 
  817                 currentCaseName = null;
 
  818                 LOGGER.log(Level.WARNING, 
"Unable to get current case for other occurrences content viewer", ex);
 
  821                 Map<UniquePathKey, OtherOccurrenceNodeInstanceData> correlatedNodeDataMap = 
new HashMap<>(0);
 
  824                 correlatedNodeDataMap.putAll(getCorrelatedInstances(corAttr, dataSourceName, deviceId));
 
  825                 for (OtherOccurrenceNodeInstanceData nodeData : correlatedNodeDataMap.values()) {
 
  826                     for (
int selectedRow : selectedCaseIndexes) {
 
  828                             if (nodeData.isCentralRepoNode()) {
 
  829                                 if (casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedRow)) != null
 
  830                                         && casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedRow)).getCaseUUID().equals(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID())) {
 
  831                                     dataSourcesTableModel.addNodeData(nodeData);
 
  833                             } 
else if (currentCaseName != null && (casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedRow)).getCaseUUID().equals(currentCaseName))) {
 
  834                                 dataSourcesTableModel.addNodeData(nodeData);
 
  837                             LOGGER.log(Level.WARNING, 
"Unable to get correlation attribute instance from OtherOccurrenceNodeInstanceData for case " + nodeData.getCaseName(), ex);
 
  842             if (dataSourcesTable.getRowCount() > 0) {
 
  843                 dataSourcesTable.setRowSelectionInterval(0, 0);
 
  853         int[] selectedDataSources = dataSourcesTable.getSelectedRows();
 
  854         filesTableModel.clearTable();
 
  856             Map<UniquePathKey, OtherOccurrenceNodeInstanceData> correlatedNodeDataMap = 
new HashMap<>(0);
 
  859             correlatedNodeDataMap.putAll(getCorrelatedInstances(corAttr, dataSourceName, deviceId));
 
  860             for (OtherOccurrenceNodeInstanceData nodeData : correlatedNodeDataMap.values()) {
 
  861                 for (
int selectedDataSourceRow : selectedDataSources) {
 
  863                         if (nodeData.isCentralRepoNode()) {
 
  864                             if (dataSourcesTableModel.getCaseUUIDForRow(dataSourcesTable.convertRowIndexToModel(selectedDataSourceRow)).equals(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID())
 
  865                                     && dataSourcesTableModel.getDeviceIdForRow(dataSourcesTable.convertRowIndexToModel(selectedDataSourceRow)).equals(nodeData.getDeviceID())) {
 
  866                                 filesTableModel.addNodeData(nodeData);
 
  869                             if (dataSourcesTableModel.getDeviceIdForRow(dataSourcesTable.convertRowIndexToModel(selectedDataSourceRow)).equals(nodeData.getDeviceID())) {
 
  870                                 filesTableModel.addNodeData(nodeData);
 
  874                         LOGGER.log(Level.WARNING, 
"Unable to get correlation attribute instance from OtherOccurrenceNodeInstanceData for case " + nodeData.getCaseName(), ex);
 
  879         if (filesTable.getRowCount() > 0) {
 
  880             filesTable.setRowSelectionInterval(0, 0);
 
  889         if (filesTable.getSelectedRowCount() == 1) {
 
  891             occurrencePanel = 
new OccurrencePanel(filesTableModel.getListOfNodesForFile(filesTable.convertRowIndexToModel(filesTable.getSelectedRow())));
 
  892         } 
else if (dataSourcesTable.getSelectedRowCount() == 1) {
 
  894             String caseName = dataSourcesTableModel.getCaseNameForRow(dataSourcesTable.convertRowIndexToModel(dataSourcesTable.getSelectedRow()));
 
  895             String dsName = dataSourcesTableModel.getValueAt(dataSourcesTable.convertRowIndexToModel(dataSourcesTable.getSelectedRow()), 0).toString();
 
  896             String caseCreatedDate = 
"";
 
  897             for (
int row : casesTable.getSelectedRows()) {
 
  898                 if (casesTableModel.
getValueAt(casesTable.convertRowIndexToModel(row), 0).toString().equals(caseName)) {
 
  899                     caseCreatedDate = getCaseCreatedDate(row);
 
  903             occurrencePanel = 
new OccurrencePanel(caseName, caseCreatedDate, dsName);
 
  904         } 
else if (casesTable.getSelectedRowCount() == 1) {
 
  907             String createdDate = 
"";
 
  908             String caseName = 
"";
 
  909             if (casesTable.getRowCount() > 0) {
 
  910                 caseName = casesTableModel.
getValueAt(casesTable.convertRowIndexToModel(casesTable.getSelectedRow()), 0).toString();
 
  912             if (caseName.isEmpty()) {
 
  913                 occurrencePanel = 
new OccurrencePanel();
 
  915                 createdDate = getCaseCreatedDate(casesTable.getSelectedRow());
 
  916                 occurrencePanel = 
new OccurrencePanel(caseName, createdDate);
 
  920             occurrencePanel = 
new OccurrencePanel();
 
  923         occurrencePanel.getPreferredSize();
 
  924         detailsPanelScrollPane.setViewportView(occurrencePanel);
 
  939                 partialCase = casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(caseTableRowIdx));
 
  940                 if (partialCase == null) {
 
  948             LOGGER.log(Level.WARNING, 
"Error getting case created date for row: " + caseTableRowIdx, ex);
 
  958     @SuppressWarnings(
"unchecked")
 
  960     private 
void initComponents() {
 
  961         java.awt.GridBagConstraints gridBagConstraints;
 
  963         rightClickPopupMenu = 
new javax.swing.JPopupMenu();
 
  964         exportToCSVMenuItem = 
new javax.swing.JMenuItem();
 
  965         showCaseDetailsMenuItem = 
new javax.swing.JMenuItem();
 
  966         showCommonalityMenuItem = 
new javax.swing.JMenuItem();
 
  967         CSVFileChooser = 
new javax.swing.JFileChooser();
 
  968         tableContainerPanel = 
new javax.swing.JPanel();
 
  969         tablesViewerSplitPane = 
new javax.swing.JSplitPane();
 
  970         caseDatasourceFileSplitPane = 
new javax.swing.JSplitPane();
 
  971         caseDatasourceSplitPane = 
new javax.swing.JSplitPane();
 
  972         caseScrollPane = 
new javax.swing.JScrollPane();
 
  973         casesTable = 
new javax.swing.JTable();
 
  974         dataSourceScrollPane = 
new javax.swing.JScrollPane();
 
  975         dataSourcesTable = 
new javax.swing.JTable();
 
  976         filesTableScrollPane = 
new javax.swing.JScrollPane();
 
  977         filesTable = 
new javax.swing.JTable();
 
  978         detailsPanelScrollPane = 
new javax.swing.JScrollPane();
 
  979         jPanel1 = 
new javax.swing.JPanel();
 
  980         foundInLabel = 
new javax.swing.JLabel();
 
  981         earliestCaseDate = 
new javax.swing.JLabel();
 
  982         earliestCaseLabel = 
new javax.swing.JLabel();
 
  983         filler1 = 
new javax.swing.Box.Filler(
new java.awt.Dimension(0, 0), 
new java.awt.Dimension(0, 0), 
new java.awt.Dimension(32767, 0));
 
  985         rightClickPopupMenu.addPopupMenuListener(
new javax.swing.event.PopupMenuListener() {
 
  986             public void popupMenuCanceled(javax.swing.event.PopupMenuEvent evt) {
 
  988             public void popupMenuWillBecomeInvisible(javax.swing.event.PopupMenuEvent evt) {
 
  990             public void popupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt) {
 
  991                 rightClickPopupMenuPopupMenuWillBecomeVisible(evt);
 
  995         org.openide.awt.Mnemonics.setLocalizedText(exportToCSVMenuItem, 
org.openide.util.NbBundle.getMessage(
DataContentViewerOtherCases.class, 
"DataContentViewerOtherCases.exportToCSVMenuItem.text")); 
 
  996         rightClickPopupMenu.add(exportToCSVMenuItem);
 
  998         org.openide.awt.Mnemonics.setLocalizedText(showCaseDetailsMenuItem, 
org.openide.util.NbBundle.getMessage(
DataContentViewerOtherCases.class, 
"DataContentViewerOtherCases.showCaseDetailsMenuItem.text")); 
 
  999         rightClickPopupMenu.add(showCaseDetailsMenuItem);
 
 1001         org.openide.awt.Mnemonics.setLocalizedText(showCommonalityMenuItem, 
org.openide.util.NbBundle.getMessage(
DataContentViewerOtherCases.class, 
"DataContentViewerOtherCases.showCommonalityMenuItem.text")); 
 
 1002         rightClickPopupMenu.add(showCommonalityMenuItem);
 
 1004         setMinimumSize(
new java.awt.Dimension(1000, 10));
 
 1006         setPreferredSize(
new java.awt.Dimension(1000, 63));
 
 1008         tableContainerPanel.setPreferredSize(
new java.awt.Dimension(600, 63));
 
 1009         tableContainerPanel.setRequestFocusEnabled(
false);
 
 1011         tablesViewerSplitPane.setDividerLocation(450);
 
 1012         tablesViewerSplitPane.setResizeWeight(0.75);
 
 1014         caseDatasourceFileSplitPane.setDividerLocation(300);
 
 1015         caseDatasourceFileSplitPane.setResizeWeight(0.66);
 
 1016         caseDatasourceFileSplitPane.setToolTipText(
"");
 
 1018         caseDatasourceSplitPane.setDividerLocation(150);
 
 1019         caseDatasourceSplitPane.setResizeWeight(0.5);
 
 1021         caseScrollPane.setPreferredSize(
new java.awt.Dimension(150, 30));
 
 1023         casesTable.setAutoCreateRowSorter(
true);
 
 1024         casesTable.setModel(casesTableModel);
 
 1025         caseScrollPane.setViewportView(casesTable);
 
 1027         caseDatasourceSplitPane.setLeftComponent(caseScrollPane);
 
 1029         dataSourceScrollPane.setPreferredSize(
new java.awt.Dimension(150, 30));
 
 1031         dataSourcesTable.setAutoCreateRowSorter(
true);
 
 1032         dataSourcesTable.setModel(dataSourcesTableModel);
 
 1033         dataSourceScrollPane.setViewportView(dataSourcesTable);
 
 1035         caseDatasourceSplitPane.setRightComponent(dataSourceScrollPane);
 
 1037         caseDatasourceFileSplitPane.setLeftComponent(caseDatasourceSplitPane);
 
 1039         filesTableScrollPane.setPreferredSize(
new java.awt.Dimension(150, 30));
 
 1041         filesTable.setAutoCreateRowSorter(
true);
 
 1042         filesTable.setModel(filesTableModel);
 
 1043         filesTable.setToolTipText(
org.openide.util.NbBundle.getMessage(
DataContentViewerOtherCases.class, 
"DataContentViewerOtherCases.table.toolTip.text")); 
 
 1044         filesTable.setComponentPopupMenu(rightClickPopupMenu);
 
 1045         filesTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
 
 1046         filesTableScrollPane.setViewportView(filesTable);
 
 1048         caseDatasourceFileSplitPane.setRightComponent(filesTableScrollPane);
 
 1050         tablesViewerSplitPane.setLeftComponent(caseDatasourceFileSplitPane);
 
 1052         detailsPanelScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
 
 1053         detailsPanelScrollPane.setPreferredSize(
new java.awt.Dimension(300, 100));
 
 1054         tablesViewerSplitPane.setRightComponent(detailsPanelScrollPane);
 
 1056         jPanel1.setPreferredSize(
new java.awt.Dimension(576, 22));
 
 1057         jPanel1.setLayout(
new java.awt.GridBagLayout());
 
 1059         foundInLabel.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
 
 1060         org.openide.awt.Mnemonics.setLocalizedText(foundInLabel, 
org.openide.util.NbBundle.getMessage(
DataContentViewerOtherCases.class, 
"DataContentViewerOtherCases.foundInLabel.text")); 
 
 1061         foundInLabel.setPreferredSize(
new java.awt.Dimension(400, 16));
 
 1062         gridBagConstraints = 
new java.awt.GridBagConstraints();
 
 1063         gridBagConstraints.gridx = 3;
 
 1064         gridBagConstraints.gridy = 0;
 
 1065         gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
 
 1066         gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST;
 
 1067         gridBagConstraints.insets = 
new java.awt.Insets(2, 2, 0, 0);
 
 1068         jPanel1.add(foundInLabel, gridBagConstraints);
 
 1070         org.openide.awt.Mnemonics.setLocalizedText(earliestCaseDate, 
org.openide.util.NbBundle.getMessage(
DataContentViewerOtherCases.class, 
"DataContentViewerOtherCases.earliestCaseDate.text")); 
 
 1071         earliestCaseDate.setMaximumSize(
new java.awt.Dimension(200, 16));
 
 1072         gridBagConstraints = 
new java.awt.GridBagConstraints();
 
 1073         gridBagConstraints.gridx = 1;
 
 1074         gridBagConstraints.gridy = 0;
 
 1075         gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
 
 1076         gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 
 1077         gridBagConstraints.insets = 
new java.awt.Insets(0, 7, 0, 0);
 
 1078         jPanel1.add(earliestCaseDate, gridBagConstraints);
 
 1080         org.openide.awt.Mnemonics.setLocalizedText(earliestCaseLabel, 
org.openide.util.NbBundle.getMessage(
DataContentViewerOtherCases.class, 
"DataContentViewerOtherCases.earliestCaseLabel.text")); 
 
 1081         earliestCaseLabel.setToolTipText(
org.openide.util.NbBundle.getMessage(
DataContentViewerOtherCases.class, 
"DataContentViewerOtherCases.earliestCaseLabel.toolTipText")); 
 
 1082         earliestCaseLabel.setMaximumSize(
new java.awt.Dimension(260, 16));
 
 1083         gridBagConstraints = 
new java.awt.GridBagConstraints();
 
 1084         gridBagConstraints.gridx = 0;
 
 1085         gridBagConstraints.gridy = 0;
 
 1086         gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
 
 1087         gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
 
 1088         jPanel1.add(earliestCaseLabel, gridBagConstraints);
 
 1089         gridBagConstraints = 
new java.awt.GridBagConstraints();
 
 1090         gridBagConstraints.gridx = 2;
 
 1091         gridBagConstraints.gridy = 0;
 
 1092         gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
 
 1093         gridBagConstraints.weightx = 0.1;
 
 1094         jPanel1.add(filler1, gridBagConstraints);
 
 1096         javax.swing.GroupLayout tableContainerPanelLayout = 
new javax.swing.GroupLayout(tableContainerPanel);
 
 1097         tableContainerPanel.setLayout(tableContainerPanelLayout);
 
 1098         tableContainerPanelLayout.setHorizontalGroup(
 
 1099             tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
 1100             .addGroup(tableContainerPanelLayout.createSequentialGroup()
 
 1101                 .addGroup(tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
 1102                     .addComponent(tablesViewerSplitPane)
 
 1103                     .addComponent(jPanel1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
 
 1106         tableContainerPanelLayout.setVerticalGroup(
 
 1107             tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
 1108             .addGroup(tableContainerPanelLayout.createSequentialGroup()
 
 1110                 .addComponent(tablesViewerSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 37, Short.MAX_VALUE)
 
 1111                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
 1112                 .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
 
 1113                 .addGap(12, 12, 12))
 
 1116         javax.swing.GroupLayout layout = 
new javax.swing.GroupLayout(
this);
 
 1117         this.setLayout(layout);
 
 1118         layout.setHorizontalGroup(
 
 1119             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
 1120             .addComponent(tableContainerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 1000, Short.MAX_VALUE)
 
 1122         layout.setVerticalGroup(
 
 1123             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
 1124             .addGroup(layout.createSequentialGroup()
 
 1125                 .addComponent(tableContainerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 78, Short.MAX_VALUE)
 
 1131         boolean enableCentralRepoActions = 
false;
 
 1133             int rowIndex = filesTable.getSelectedRow();
 
 1134             List<OtherOccurrenceNodeData> selectedFile = filesTableModel.getListOfNodesForFile(rowIndex);
 
 1135             if (!selectedFile.isEmpty() && selectedFile.get(0) instanceof OtherOccurrenceNodeInstanceData) {
 
 1136                 OtherOccurrenceNodeInstanceData instanceData = (OtherOccurrenceNodeInstanceData) selectedFile.get(0);
 
 1137                 enableCentralRepoActions = instanceData.isCentralRepoNode();
 
 1140         showCaseDetailsMenuItem.setVisible(enableCentralRepoActions);
 
 1141         showCommonalityMenuItem.setVisible(enableCentralRepoActions);
 
 1181             dataSourceID = nodeData.getDeviceID();
 
 1182             if (nodeData.getFilePath() != null) {
 
 1183                 filePath = nodeData.getFilePath().toLowerCase();
 
 1187             type = nodeData.getType();
 
 1188             String tempCaseUUID;
 
 1190                 tempCaseUUID = nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID();
 
 1196                 } 
catch (NoCurrentCaseException ex) {
 
 1197                     LOGGER.log(Level.WARNING, 
"Unable to get current case", ex);
 
 1198                     tempCaseUUID = UUID_PLACEHOLDER_STRING;
 
 1201             caseUUID = tempCaseUUID;
 
 1207                 UniquePathKey otherKey = (UniquePathKey) (other);
 
 1208                 return (Objects.equals(otherKey.getDataSourceID(), this.getDataSourceID())
 
 1209                         && Objects.equals(otherKey.getFilePath(), this.getFilePath())
 
 1210                         && Objects.equals(otherKey.getType(), this.getType())
 
 1211                         && Objects.equals(otherKey.getCaseUUID(), this.getCaseUUID()));
 
 1218             return Objects.hash(getDataSourceID(), getFilePath(), getType(), getCaseUUID());
 
 1235         String getFilePath() {
 
 1244         String getDataSourceID() {
 
 1245             return dataSourceID;
 
 1253         String getCaseUUID() {
 
Object getValueAt(int rowIdx, int colIdx)
final Collection< CorrelationAttributeInstance > correlationAttributes
void updateOnFileSelection()
void rightClickPopupMenuPopupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt)
final OtherOccurrencesFilesTableModel filesTableModel
boolean equals(Object other)
List< CorrelationCase > getCases()
String makeDataSourceString(String caseUUID, String deviceId, String dataSourceName)
int isPreferred(Node node)
javax.swing.JLabel earliestCaseLabel
javax.swing.JMenuItem showCommonalityMenuItem
void updateOnDataSourceSelection()
List< CorrelationAttributeInstance > getArtifactInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String value)
static CorrelationDataSource fromTSKDataSource(CorrelationCase correlationCase, Content dataSource)
javax.swing.JPanel tableContainerPanel
void setEarliestCaseDate()
javax.swing.JSplitPane caseDatasourceFileSplitPane
AbstractFile getAbstractFileFromNode(Node node)
CorrelationCase getCase(Case autopsyCase)
static List< CorrelationAttributeInstance.Type > getDefaultCorrelationTypes()
CorrelationCase getCaseByUUID(String caseUUID)
javax.swing.JTable dataSourcesTable
Collection< CorrelationAttributeInstance > getCorrelationAttributesFromNode(Node node)
String getCorrelationValue()
final String dataSourceID
javax.swing.JScrollPane detailsPanelScrollPane
javax.swing.JSplitPane tablesViewerSplitPane
javax.swing.JScrollPane filesTableScrollPane
void writeOtherOccurrencesToFileAsCSV(File destFile)
List< CorrelationAttributeInstance.Type > getDefinedCorrelationTypes()
javax.swing.Box.Filler filler1
static List< CorrelationAttributeInstance > makeCorrAttrsForCorrelation(BlackboardArtifact artifact)
Type getCorrelationType()
void populateTable(Node node)
javax.swing.JPopupMenu rightClickPopupMenu
javax.swing.JSplitPane caseDatasourceSplitPane
javax.swing.JScrollPane dataSourceScrollPane
javax.swing.JScrollPane caseScrollPane
BlackboardArtifact getBlackboardArtifactFromNode(Node node)
void updateOnCaseSelection()
boolean isSupported(Node node)
javax.swing.JPanel jPanel1
String getCaseDetailsOptionsPaneDialog()
void showCaseDetails(int selectedRowViewIdx)
javax.swing.JMenuItem exportToCSVMenuItem
SleuthkitCase getSleuthkitCase()
void addOrUpdateNodeData(final Case autopsyCase, Map< UniquePathKey, OtherOccurrenceNodeInstanceData > nodeDataMap, AbstractFile newFile)
void showCommonalityDetails()
OccurrencePanel occurrencePanel
DataContentViewerOtherCases()
int getFrequencyPercentage(CorrelationAttributeInstance corAttr)
javax.swing.JFileChooser CSVFileChooser
javax.swing.JLabel earliestCaseDate
static Case getCurrentCase()
synchronized static Logger getLogger(String name)
final OtherOccurrencesCasesTableModel casesTableModel
static Case getCurrentCaseThrows()
javax.swing.JLabel foundInLabel
String getExportDirectory()
javax.swing.JTable filesTable
DataContentViewer createInstance()
void customizeComponents()
List< AbstractFile > getCaseDbMatches(CorrelationAttributeInstance corAttr, Case openCase)
Map< UniquePathKey, OtherOccurrenceNodeInstanceData > getCorrelatedInstances(CorrelationAttributeInstance corAttr, String dataSourceName, String deviceId)
String getCaseCreatedDate(int caseTableRowIdx)
static CentralRepository getInstance()
static boolean isCaseOpen()
javax.swing.JTable casesTable
final OtherOccurrencesDataSourcesTableModel dataSourcesTableModel
static final int FILES_TYPE_ID
javax.swing.JMenuItem showCaseDetailsMenuItem
static boolean isEnabled()