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.io.BufferedWriter;
 
   26 import java.io.IOException;
 
   27 import java.nio.file.Files;
 
   28 import java.text.DateFormat;
 
   29 import java.text.ParseException;
 
   30 import java.text.SimpleDateFormat;
 
   31 import java.util.ArrayList;
 
   32 import java.util.Calendar;
 
   33 import java.util.Collection;
 
   34 import java.util.HashMap;
 
   35 import java.util.HashSet;
 
   36 import java.util.List;
 
   37 import java.util.Locale;
 
   39 import java.util.Objects;
 
   41 import java.util.logging.Level;
 
   43 import javax.swing.JFileChooser;
 
   44 import javax.swing.JMenuItem;
 
   45 import javax.swing.JOptionPane;
 
   46 import static javax.swing.JOptionPane.DEFAULT_OPTION;
 
   47 import static javax.swing.JOptionPane.PLAIN_MESSAGE;
 
   48 import static javax.swing.JOptionPane.ERROR_MESSAGE;
 
   49 import javax.swing.JPanel;
 
   50 import javax.swing.filechooser.FileNameExtensionFilter;
 
   51 import javax.swing.table.DefaultTableModel;
 
   52 import javax.swing.table.TableCellRenderer;
 
   53 import javax.swing.table.TableColumn;
 
   54 import javax.swing.table.TableModel;
 
   55 import javax.swing.table.TableRowSorter;
 
   56 import org.joda.time.DateTimeZone;
 
   57 import org.joda.time.LocalDateTime;
 
   58 import org.openide.nodes.Node;
 
   59 import org.openide.util.NbBundle.Messages;
 
   60 import org.openide.util.lookup.ServiceProvider;
 
   84 @SuppressWarnings(
"PMD.SingularField") 
 
   85 @ServiceProvider(service = DataContentViewer.class, position = 9)
 
   86 @Messages({
"DataContentViewerOtherCases.title=Other Occurrences",
 
   87     "DataContentViewerOtherCases.toolTip=Displays instances of the selected file/artifact from other occurrences.",
 
   88     "DataContentViewerOtherCases.table.noArtifacts=Item has no attributes with which to search.",
 
   89     "DataContentViewerOtherCases.table.noResultsFound=No results found."})
 
   92     private static final long serialVersionUID = -1L;
 
   95     private static final CorrelationCaseWrapper NO_ARTIFACTS_CASE = 
new CorrelationCaseWrapper(Bundle.DataContentViewerOtherCases_table_noArtifacts());
 
   96     private static final CorrelationCaseWrapper NO_RESULTS_CASE = 
new CorrelationCaseWrapper(Bundle.DataContentViewerOtherCases_table_noArtifacts());
 
   97     private static final int DEFAULT_MIN_CELL_WIDTH = 15;
 
  102     private String dataSourceName = 
"";
 
  103     private String deviceId = 
"";
 
  115         this.correlationAttributes = 
new ArrayList<>();
 
  118         customizeComponents();
 
  123         ActionListener actList = 
new ActionListener() {
 
  125             public void actionPerformed(ActionEvent e) {
 
  126                 JMenuItem jmi = (JMenuItem) e.getSource();
 
  127                 if (jmi.equals(selectAllMenuItem)) {
 
  128                     filesTable.selectAll();
 
  129                 } 
else if (jmi.equals(showCaseDetailsMenuItem)) {
 
  130                     showCaseDetails(filesTable.getSelectedRow());
 
  131                 } 
else if (jmi.equals(exportToCSVMenuItem)) {
 
  135                         LOGGER.log(Level.SEVERE, 
"Exception while getting open case.", ex); 
 
  137                 } 
else if (jmi.equals(showCommonalityMenuItem)) {
 
  138                     showCommonalityDetails();
 
  143         exportToCSVMenuItem.addActionListener(actList);
 
  144         selectAllMenuItem.addActionListener(actList);
 
  145         showCaseDetailsMenuItem.addActionListener(actList);
 
  146         showCommonalityMenuItem.addActionListener(actList);
 
  150         filesTable.setDefaultRenderer(Object.class, renderer);
 
  153         TableRowSorter<TableModel> sorter = 
new TableRowSorter<>(filesTable.getModel());
 
  154         filesTable.setRowSorter(sorter);
 
  155         casesTable.getSelectionModel().addListSelectionListener((e) -> {
 
  157                 updateOnCaseSelection();
 
  160         dataSourcesTable.getSelectionModel().addListSelectionListener((e) -> {
 
  162                 updateOnDataSourceSelection();
 
  165         casesTable.getRowSorter().toggleSortOrder(0);
 
  166         dataSourcesTable.getRowSorter().toggleSortOrder(0);
 
  169     @Messages({
"DataContentViewerOtherCases.correlatedArtifacts.isEmpty=There are no files or artifacts to correlate.",
 
  170         "# {0} - commonality percentage",
 
  171         "# {1} - correlation type",
 
  172         "# {2} - correlation value",
 
  173         "DataContentViewerOtherCases.correlatedArtifacts.byType={0}% of data sources have {2} (type: {1})\n",
 
  174         "DataContentViewerOtherCases.correlatedArtifacts.title=Attribute Frequency",
 
  175         "DataContentViewerOtherCases.correlatedArtifacts.failed=Failed to get frequency details."})
 
  181         if (correlationAttributes.isEmpty()) {
 
  182             JOptionPane.showConfirmDialog(showCommonalityMenuItem,
 
  183                     Bundle.DataContentViewerOtherCases_correlatedArtifacts_isEmpty(),
 
  184                     Bundle.DataContentViewerOtherCases_correlatedArtifacts_title(),
 
  185                     DEFAULT_OPTION, PLAIN_MESSAGE);
 
  187             StringBuilder msg = 
new StringBuilder(correlationAttributes.size());
 
  194                         msg.append(Bundle.DataContentViewerOtherCases_correlatedArtifacts_byType(percentage,
 
  195                                 eamArtifact.getCorrelationType().getDisplayName(),
 
  196                                 eamArtifact.getCorrelationValue()));
 
  198                         LOGGER.log(Level.WARNING, String.format(
"Error getting commonality details for artifact with ID: %s.", eamArtifact.getID()), ex);
 
  201                 JOptionPane.showConfirmDialog(showCommonalityMenuItem,
 
  203                         Bundle.DataContentViewerOtherCases_correlatedArtifacts_title(),
 
  204                         DEFAULT_OPTION, PLAIN_MESSAGE);
 
  206                 LOGGER.log(Level.SEVERE, 
"Error getting commonality details.", ex);
 
  207                 JOptionPane.showConfirmDialog(showCommonalityMenuItem,
 
  208                         Bundle.DataContentViewerOtherCases_correlatedArtifacts_failed(),
 
  209                         Bundle.DataContentViewerOtherCases_correlatedArtifacts_title(),
 
  210                         DEFAULT_OPTION, ERROR_MESSAGE);
 
  215     @Messages({
"DataContentViewerOtherCases.caseDetailsDialog.notSelected=No Row Selected",
 
  216         "DataContentViewerOtherCases.caseDetailsDialog.noDetails=No details for this case.",
 
  217         "DataContentViewerOtherCases.caseDetailsDialog.noDetailsReference=No case details for Global reference properties.",
 
  218         "DataContentViewerOtherCases.caseDetailsDialog.noCaseNameError=Error",
 
  219         "DataContentViewerOtherCases.noOpenCase.errMsg=No open case available."})
 
  222         String caseDisplayName = Bundle.DataContentViewerOtherCases_caseDetailsDialog_noCaseNameError();
 
  224             if (-1 != selectedRowViewIdx) {
 
  226                 int selectedRowModelIdx = filesTable.convertRowIndexToModel(selectedRowViewIdx);
 
  227                 OtherOccurrenceNodeInstanceData nodeData = (OtherOccurrenceNodeInstanceData) tableModel.getRow(selectedRowModelIdx);
 
  228                 CorrelationCase eamCasePartial = nodeData.getCorrelationAttributeInstance().getCorrelationCase();
 
  229                 if (eamCasePartial == null) {
 
  230                     JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
 
  231                             Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetailsReference(),
 
  233                             DEFAULT_OPTION, PLAIN_MESSAGE);
 
  239                 if (eamCase == null) {
 
  240                     JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
 
  241                             Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetails(),
 
  243                             DEFAULT_OPTION, PLAIN_MESSAGE);
 
  248                 JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
 
  251                         DEFAULT_OPTION, PLAIN_MESSAGE);
 
  253                 JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
 
  254                         Bundle.DataContentViewerOtherCases_caseDetailsDialog_notSelected(),
 
  256                         DEFAULT_OPTION, PLAIN_MESSAGE);
 
  259             LOGGER.log(Level.SEVERE, 
"Error loading case details", ex);
 
  260             JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
 
  261                     Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetails(),
 
  263                     DEFAULT_OPTION, PLAIN_MESSAGE);
 
  268         if (0 != filesTable.getSelectedRowCount()) {
 
  269             Calendar now = Calendar.getInstance();
 
  270             String fileName = String.format(
"%1$tY%1$tm%1$te%1$tI%1$tM%1$tS_other_data_sources.csv", now);
 
  272             CSVFileChooser.setSelectedFile(
new File(fileName));
 
  273             CSVFileChooser.setFileFilter(
new FileNameExtensionFilter(
"csv file", 
"csv"));
 
  275             int returnVal = CSVFileChooser.showSaveDialog(filesTable);
 
  276             if (returnVal == JFileChooser.APPROVE_OPTION) {
 
  278                 File selectedFile = CSVFileChooser.getSelectedFile();
 
  279                 if (!selectedFile.getName().endsWith(
".csv")) { 
 
  280                     selectedFile = 
new File(selectedFile.toString() + 
".csv"); 
 
  283                 writeSelectedRowsToFileAsCSV(selectedFile);
 
  289         StringBuilder content;
 
  290         int[] selectedRowViewIndices = filesTable.getSelectedRows();
 
  293         try (BufferedWriter writer = Files.newBufferedWriter(destFile.toPath())) {
 
  296             content = 
new StringBuilder(
"");
 
  297             for (
int colIdx = 0; colIdx < colCount; colIdx++) {
 
  298                 content.append(
'"').append(tableModel.
getColumnName(colIdx)).append(
'"');
 
  299                 if (colIdx < (colCount - 1)) {
 
  304             content.append(System.getProperty(
"line.separator"));
 
  305             writer.write(content.toString());
 
  308             for (
int rowViewIdx : selectedRowViewIndices) {
 
  309                 content = 
new StringBuilder(
"");
 
  310                 for (
int colIdx = 0; colIdx < colCount; colIdx++) {
 
  311                     int rowModelIdx = filesTable.convertRowIndexToModel(rowViewIdx);
 
  312                     content.append(
'"').append(tableModel.
getValueAt(rowModelIdx, colIdx)).append(
'"');
 
  313                     if (colIdx < (colCount - 1)) {
 
  317                 content.append(System.getProperty(
"line.separator"));
 
  318                 writer.write(content.toString());
 
  321         } 
catch (IOException ex) {
 
  322             LOGGER.log(Level.SEVERE, 
"Error writing selected rows to CSV.", ex);
 
  331         casesTableModel.clearTable();
 
  332         ((DefaultTableModel) dataSourcesTable.getModel()).setRowCount(0);
 
  333         tableModel.clearTable();
 
  334         correlationAttributes.clear();
 
  335         earliestCaseDate.setText(Bundle.DataContentViewerOtherCases_earliestCaseNotAvailable());
 
  336         foundInLabel.setText(
"");
 
  341         return Bundle.DataContentViewerOtherCases_title();
 
  346         return Bundle.DataContentViewerOtherCases_toolTip();
 
  376     private BlackboardArtifact
 
  378         BlackboardArtifactTag nodeBbArtifactTag = node.getLookup().lookup(BlackboardArtifactTag.class
 
  380         BlackboardArtifact nodeBbArtifact = node.getLookup().lookup(BlackboardArtifact.class
 
  383         if (nodeBbArtifactTag != null) {
 
  384             return nodeBbArtifactTag.getArtifact();
 
  385         } 
else if (nodeBbArtifact != null) {
 
  386             return nodeBbArtifact;
 
  401         BlackboardArtifactTag nodeBbArtifactTag = node.getLookup().lookup(BlackboardArtifactTag.class
 
  403         ContentTag nodeContentTag = node.getLookup().lookup(ContentTag.class
 
  405         BlackboardArtifact nodeBbArtifact = node.getLookup().lookup(BlackboardArtifact.class
 
  407         AbstractFile nodeAbstractFile = node.getLookup().lookup(AbstractFile.class
 
  410         if (nodeBbArtifactTag != null) {
 
  411             Content content = nodeBbArtifactTag.getContent();
 
  412             if (content instanceof AbstractFile) {
 
  413                 return (AbstractFile) content;
 
  415         } 
else if (nodeContentTag != null) {
 
  416             Content content = nodeContentTag.getContent();
 
  417             if (content instanceof AbstractFile) {
 
  418                 return (AbstractFile) content;
 
  420         } 
else if (nodeBbArtifact != null) {
 
  423                 content = nodeBbArtifact.getSleuthkitCase().getContentById(nodeBbArtifact.getObjectID());
 
  424             } 
catch (TskCoreException ex) {
 
  425                 LOGGER.log(Level.SEVERE, 
"Error retrieving blackboard artifact", ex); 
 
  429             if (content instanceof AbstractFile) {
 
  430                 return (AbstractFile) content;
 
  432         } 
else if (nodeAbstractFile != null) {
 
  433             return nodeAbstractFile;
 
  448         Collection<CorrelationAttributeInstance> ret = 
new ArrayList<>();
 
  451         BlackboardArtifact bbArtifact = getBlackboardArtifactFromNode(node);
 
  457         if (this.file != null && 
EamDb.
isEnabled() && this.file.getSize() > 0) {
 
  461                 String md5 = this.file.getMd5Hash();
 
  462                 if (md5 != null && !md5.isEmpty() && null != artifactTypes && !artifactTypes.isEmpty()) {
 
  472                                         file.getParentPath() + file.
getName(),
 
  477                                 LOGGER.log(Level.INFO, String.format(
"Unable to check create CorrelationAttribtueInstance for value %s and type %s.", md5, aType.toString()), ex);
 
  484                 LOGGER.log(Level.SEVERE, 
"Error connecting to DB", ex); 
 
  487         } 
else if (this.file != null && this.file.getSize() > 0) {
 
  488             String md5 = this.file.getMd5Hash();
 
  489             if (md5 != null && !md5.isEmpty()) {
 
  500                     LOGGER.log(Level.SEVERE, 
"Error connecting to DB", ex); 
 
  502                     LOGGER.log(Level.INFO, String.format(
"Unable to create CorrelationAttributeInstance for value %s", md5), ex); 
 
  510     @Messages({
"DataContentViewerOtherCases.earliestCaseNotAvailable= Not Enabled."})
 
  516         String dateStringDisplay = Bundle.DataContentViewerOtherCases_earliestCaseNotAvailable();
 
  519             LocalDateTime earliestDate = LocalDateTime.now(DateTimeZone.UTC);
 
  520             DateFormat datetimeFormat = 
new SimpleDateFormat(
"yyyy/MM/dd HH:mm:ss", Locale.US);
 
  523                 List<CorrelationCase> cases = dbManager.
getCases();
 
  525                     LocalDateTime caseDate = LocalDateTime.fromDateFields(datetimeFormat.parse(aCase.getCreationDate()));
 
  527                     if (caseDate.isBefore(earliestDate)) {
 
  528                         earliestDate = caseDate;
 
  529                         dateStringDisplay = aCase.getCreationDate();
 
  535                 LOGGER.log(Level.SEVERE, 
"Error getting list of cases from database.", ex); 
 
  536             } 
catch (ParseException ex) {
 
  537                 LOGGER.log(Level.SEVERE, 
"Error parsing date of cases from database.", ex); 
 
  541         earliestCaseDate.setText(dateStringDisplay);
 
  560             String caseUUID = openCase.
getName();
 
  562             HashMap<UniquePathKey, OtherOccurrenceNodeInstanceData> nodeDataMap = 
new HashMap<>();
 
  575                     if (!artifactInstance.getCorrelationCase().getCaseUUID().equals(caseUUID)
 
  576                             || !artifactInstance.getCorrelationDataSource().getName().equals(dataSourceName)
 
  577                             || !artifactInstance.getCorrelationDataSource().getDeviceID().equals(deviceId)
 
  578                             || !artifactInstance.getFilePath().equalsIgnoreCase(file.getParentPath() + file.getName())) {
 
  582                         nodeDataMap.put(uniquePathKey, newNode);
 
  588                 List<AbstractFile> caseDbFiles = getCaseDbMatches(corAttr, openCase);
 
  590                 for (AbstractFile caseDbFile : caseDbFiles) {
 
  591                     addOrUpdateNodeData(openCase, nodeDataMap, caseDbFile);
 
  597             LOGGER.log(Level.SEVERE, 
"Error getting artifact instances from database.", ex); 
 
  599             LOGGER.log(Level.INFO, 
"Error getting artifact instances from database.", ex); 
 
  601             LOGGER.log(Level.SEVERE, 
"Exception while getting open case.", ex); 
 
  602         } 
catch (TskCoreException ex) {
 
  605             LOGGER.log(Level.SEVERE, 
"Exception while querying open case.", ex); 
 
  608         return new HashMap<>(0);
 
  625         String md5 = corAttr.getCorrelationValue();
 
  626         SleuthkitCase tsk = openCase.getSleuthkitCase();
 
  627         List<AbstractFile> matches = tsk.findAllFilesWhere(String.format(
"md5 = '%s'", 
new Object[]{md5}));
 
  629         List<AbstractFile> caseDbArtifactInstances = 
new ArrayList<>();
 
  630         for (AbstractFile fileMatch : matches) {
 
  631             if (this.file.equals(fileMatch)) {
 
  634             caseDbArtifactInstances.add(fileMatch);
 
  636         return caseDbArtifactInstances;
 
  652         OtherOccurrenceNodeInstanceData newNode = 
new OtherOccurrenceNodeInstanceData(newFile, autopsyCase);
 
  656         if (newNode.getKnown() != TskData.FileKnown.BAD) {
 
  657             List<ContentTag> fileMatchTags = autopsyCase.getServices().getTagsManager().getContentTagsByContent(newFile);
 
  658             for (ContentTag tag : fileMatchTags) {
 
  659                 TskData.FileKnown tagKnownStatus = tag.getName().getKnownStatus();
 
  660                 if (tagKnownStatus.equals(TskData.FileKnown.BAD)) {
 
  661                     newNode.updateKnown(TskData.FileKnown.BAD);
 
  673         if (nodeDataMap.containsKey(uniquePathKey)) {
 
  674             if (newNode.getKnown() == TskData.FileKnown.BAD) {
 
  675                 OtherOccurrenceNodeInstanceData prevInstance = nodeDataMap.get(uniquePathKey);
 
  676                 prevInstance.updateKnown(newNode.getKnown());
 
  679             nodeDataMap.put(uniquePathKey, newNode);
 
  690         this.file = this.getAbstractFileFromNode(node);
 
  692             return !getCorrelationAttributesFromNode(node).isEmpty();
 
  694             return this.file != null
 
  695                     && this.file.getSize() > 0
 
  696                     && ((this.file.getMd5Hash() != null) && (!this.file.getMd5Hash().isEmpty()));
 
  708         this.file = this.getAbstractFileFromNode(node);
 
  720         "DataContentViewerOtherCases.dataSources.header.text=Data Source Name",
 
  721         "DataContentViewerOtherCases.foundIn.text=Found %d instances in %d cases and %d data sources." 
  725             if (this.file != null) {
 
  726                 Content dataSource = this.file.getDataSource();
 
  727                 dataSourceName = dataSource.getName();
 
  730         } 
catch (TskException | NoCurrentCaseException ex) {
 
  736         correlationAttributes.addAll(getCorrelationAttributesFromNode(node));
 
  737         Map<String, CorrelationCase> caseNames = 
new HashMap<>();
 
  739         Set<String> dataSources = 
new HashSet<>();
 
  741             Map<UniquePathKey, OtherOccurrenceNodeInstanceData> correlatedNodeDataMap = 
new HashMap<>(0);
 
  744             correlatedNodeDataMap.putAll(getCorrelatedInstances(corAttr, dataSourceName, deviceId));
 
  745             for (OtherOccurrenceNodeInstanceData nodeData : correlatedNodeDataMap.values()) {
 
  746                 if (nodeData.isCentralRepoNode()) {
 
  748                         dataSources.add(makeDataSourceString(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID(), nodeData.getDeviceID(), nodeData.getDataSourceName()));
 
  749                         caseNames.put(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID(), nodeData.getCorrelationAttributeInstance().getCorrelationCase());
 
  751                         LOGGER.log(Level.WARNING, 
"Unable to get correlation case for displaying other occurrence for case: " + nodeData.getCaseName());
 
  757                     } 
catch (NoCurrentCaseException ex) {
 
  758                         LOGGER.log(Level.WARNING, 
"No current case open for other occurrences");
 
  765             casesTableModel.addCorrelationCase(
new CorrelationCaseWrapper(corCase));
 
  768         if (correlationAttributes.isEmpty()) {
 
  769             casesTableModel.addCorrelationCase(NO_ARTIFACTS_CASE);
 
  770         } 
else if (caseCount == 0) {
 
  771             casesTableModel.addCorrelationCase(NO_RESULTS_CASE);
 
  774         setEarliestCaseDate();
 
  775         foundInLabel.setText(String.format(Bundle.DataContentViewerOtherCases_foundIn_text(), totalCount, caseCount, dataSources.size()));
 
  777             casesTable.setRowSelectionInterval(0, 0);
 
  786         return caseUUID + deviceId + dataSourceName;
 
  793         int[] selectedCaseIndexes = casesTable.getSelectedRows();
 
  794         DefaultTableModel dataSourceModel = (DefaultTableModel) dataSourcesTable.getModel();
 
  795         dataSourceModel.setRowCount(0);
 
  796         tableModel.clearTable();
 
  798             Map<UniquePathKey, OtherOccurrenceNodeInstanceData> correlatedNodeDataMap = 
new HashMap<>(0);
 
  801             correlatedNodeDataMap.putAll(getCorrelatedInstances(corAttr, dataSourceName, deviceId));
 
  802             for (OtherOccurrenceNodeInstanceData nodeData : correlatedNodeDataMap.values()) {
 
  803                 for (
int selectedRow : selectedCaseIndexes) {
 
  805                         if (nodeData.isCentralRepoNode()) {
 
  806                             if (casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedRow)) != null
 
  807                                     && ((
CorrelationCase) casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedRow))).getCaseUUID().equals(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID())) {
 
  808                                 dataSourceModel.addRow(
new Object[]{nodeData.getDataSourceName(), nodeData.getDeviceID()});
 
  811                             dataSourceModel.addRow(
new Object[]{nodeData.getDataSourceName(), nodeData.getDeviceID()});
 
  814                         LOGGER.log(Level.WARNING, 
"Unable to get correlation attribute instance from OtherOccurrenceNodeInstanceData for case " + nodeData.getCaseName());
 
  819         if (dataSourcesTable.getRowCount() > 0) {
 
  820             dataSourcesTable.setRowSelectionInterval(0, 0);
 
  829         int[] selectedCaseIndexes = casesTable.getSelectedRows();
 
  830         DefaultTableModel dataSourceModel = (DefaultTableModel) dataSourcesTable.getModel();
 
  831         int[] selectedDataSources = dataSourcesTable.getSelectedRows();
 
  832         tableModel.clearTable();
 
  834             Map<UniquePathKey, OtherOccurrenceNodeInstanceData> correlatedNodeDataMap = 
new HashMap<>(0);
 
  837             correlatedNodeDataMap.putAll(getCorrelatedInstances(corAttr, dataSourceName, deviceId));
 
  838             for (OtherOccurrenceNodeInstanceData nodeData : correlatedNodeDataMap.values()) {
 
  839                 for (
int selectedCaseRow : selectedCaseIndexes) {
 
  840                     for (
int selectedDataSourceRow : selectedDataSources) {
 
  842                             if (nodeData.isCentralRepoNode()) {
 
  843                                 if (casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedCaseRow)) != null
 
  844                                         && ((
CorrelationCase) casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedCaseRow))).getCaseUUID().equals(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID())
 
  845                                         && dataSourceModel.getValueAt(dataSourcesTable.convertRowIndexToModel(selectedDataSourceRow), 1).toString().equals(nodeData.getDeviceID())) {
 
  846                                     tableModel.addNodeData(nodeData);
 
  849                                 if (dataSourceModel.getValueAt(dataSourcesTable.convertRowIndexToModel(selectedDataSourceRow), 1).toString().equals(nodeData.getDeviceID())) {
 
  850                                     tableModel.addNodeData(nodeData);
 
  854                             LOGGER.log(Level.WARNING, 
"Unable to get correlation attribute instance from OtherOccurrenceNodeInstanceData for case " + nodeData.getCaseName());
 
  867             TableColumn column = filesTable.getColumnModel().getColumn(idx);
 
  868             column.setMinWidth(DEFAULT_MIN_CELL_WIDTH);
 
  870             if (columnWidth > 0) {
 
  871                 column.setPreferredWidth(columnWidth);
 
  874         for (
int idx = 0; idx < dataSourcesTable.getColumnCount(); idx++) {
 
  875             if (dataSourcesTable.getColumnModel().getColumn(idx).getHeaderValue().toString().equals(Bundle.DataContentViewerOtherCases_dataSources_header_text())) {
 
  876                 dataSourcesTable.getColumnModel().getColumn(idx).setPreferredWidth(100);
 
  878                 dataSourcesTable.getColumnModel().getColumn(idx).setPreferredWidth(210);
 
  888     @SuppressWarnings(
"unchecked")
 
  890     private 
void initComponents() {
 
  892         rightClickPopupMenu = 
new javax.swing.JPopupMenu();
 
  893         selectAllMenuItem = 
new javax.swing.JMenuItem();
 
  894         exportToCSVMenuItem = 
new javax.swing.JMenuItem();
 
  895         showCaseDetailsMenuItem = 
new javax.swing.JMenuItem();
 
  896         showCommonalityMenuItem = 
new javax.swing.JMenuItem();
 
  897         CSVFileChooser = 
new javax.swing.JFileChooser();
 
  898         otherCasesPanel = 
new javax.swing.JPanel();
 
  899         tableContainerPanel = 
new javax.swing.JPanel();
 
  900         earliestCaseLabel = 
new javax.swing.JLabel();
 
  901         earliestCaseDate = 
new javax.swing.JLabel();
 
  902         foundInLabel = 
new javax.swing.JLabel();
 
  903         jSplitPane2 = 
new javax.swing.JSplitPane();
 
  904         jSplitPane3 = 
new javax.swing.JSplitPane();
 
  905         caseScrollPane = 
new javax.swing.JScrollPane();
 
  906         casesTable = 
new javax.swing.JTable();
 
  907         dataSourceScrollPane = 
new javax.swing.JScrollPane();
 
  908         dataSourcesTable = 
new javax.swing.JTable();
 
  909         propertiesTableScrollPane = 
new javax.swing.JScrollPane();
 
  910         filesTable = 
new javax.swing.JTable();
 
  912         rightClickPopupMenu.addPopupMenuListener(
new javax.swing.event.PopupMenuListener() {
 
  913             public void popupMenuCanceled(javax.swing.event.PopupMenuEvent evt) {
 
  915             public void popupMenuWillBecomeInvisible(javax.swing.event.PopupMenuEvent evt) {
 
  917             public void popupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt) {
 
  918                 rightClickPopupMenuPopupMenuWillBecomeVisible(evt);
 
  922         org.openide.awt.Mnemonics.setLocalizedText(selectAllMenuItem, 
org.openide.util.NbBundle.getMessage(
DataContentViewerOtherCases.class, 
"DataContentViewerOtherCases.selectAllMenuItem.text")); 
 
  923         rightClickPopupMenu.add(selectAllMenuItem);
 
  925         org.openide.awt.Mnemonics.setLocalizedText(exportToCSVMenuItem, 
org.openide.util.NbBundle.getMessage(
DataContentViewerOtherCases.class, 
"DataContentViewerOtherCases.exportToCSVMenuItem.text")); 
 
  926         rightClickPopupMenu.add(exportToCSVMenuItem);
 
  928         org.openide.awt.Mnemonics.setLocalizedText(showCaseDetailsMenuItem, 
org.openide.util.NbBundle.getMessage(
DataContentViewerOtherCases.class, 
"DataContentViewerOtherCases.showCaseDetailsMenuItem.text")); 
 
  929         rightClickPopupMenu.add(showCaseDetailsMenuItem);
 
  931         org.openide.awt.Mnemonics.setLocalizedText(showCommonalityMenuItem, 
org.openide.util.NbBundle.getMessage(
DataContentViewerOtherCases.class, 
"DataContentViewerOtherCases.showCommonalityMenuItem.text")); 
 
  932         rightClickPopupMenu.add(showCommonalityMenuItem);
 
  934         setMinimumSize(
new java.awt.Dimension(1500, 10));
 
  936         setPreferredSize(
new java.awt.Dimension(1500, 44));
 
  938         otherCasesPanel.setPreferredSize(
new java.awt.Dimension(921, 62));
 
  940         tableContainerPanel.setPreferredSize(
new java.awt.Dimension(1500, 63));
 
  942         org.openide.awt.Mnemonics.setLocalizedText(earliestCaseLabel, 
org.openide.util.NbBundle.getMessage(
DataContentViewerOtherCases.class, 
"DataContentViewerOtherCases.earliestCaseLabel.text")); 
 
  943         earliestCaseLabel.setToolTipText(
org.openide.util.NbBundle.getMessage(
DataContentViewerOtherCases.class, 
"DataContentViewerOtherCases.earliestCaseLabel.toolTipText")); 
 
  945         org.openide.awt.Mnemonics.setLocalizedText(earliestCaseDate, 
org.openide.util.NbBundle.getMessage(
DataContentViewerOtherCases.class, 
"DataContentViewerOtherCases.earliestCaseDate.text")); 
 
  947         org.openide.awt.Mnemonics.setLocalizedText(foundInLabel, 
org.openide.util.NbBundle.getMessage(
DataContentViewerOtherCases.class, 
"DataContentViewerOtherCases.foundInLabel.text")); 
 
  949         jSplitPane2.setDividerLocation(470);
 
  951         jSplitPane3.setDividerLocation(150);
 
  953         casesTable.setAutoCreateRowSorter(
true);
 
  954         casesTable.setModel(casesTableModel);
 
  955         caseScrollPane.setViewportView(casesTable);
 
  957         jSplitPane3.setLeftComponent(caseScrollPane);
 
  959         dataSourcesTable.setAutoCreateRowSorter(
true);
 
  960         dataSourcesTable.setModel(
new javax.swing.table.DefaultTableModel(
 
  965                 "Data Source Name", 
"Device ID" 
  968             boolean[] canEdit = 
new boolean [] {
 
  972             public boolean isCellEditable(
int rowIndex, 
int columnIndex) {
 
  973                 return canEdit [columnIndex];
 
  976         dataSourceScrollPane.setViewportView(dataSourcesTable);
 
  978         jSplitPane3.setRightComponent(dataSourceScrollPane);
 
  980         jSplitPane2.setLeftComponent(jSplitPane3);
 
  982         propertiesTableScrollPane.setPreferredSize(
new java.awt.Dimension(1000, 30));
 
  984         filesTable.setAutoCreateRowSorter(
true);
 
  985         filesTable.setModel(tableModel);
 
  986         filesTable.setToolTipText(
org.openide.util.NbBundle.getMessage(
DataContentViewerOtherCases.class, 
"DataContentViewerOtherCases.table.toolTip.text")); 
 
  987         filesTable.setComponentPopupMenu(rightClickPopupMenu);
 
  988         filesTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_INTERVAL_SELECTION);
 
  989         propertiesTableScrollPane.setViewportView(filesTable);
 
  991         jSplitPane2.setRightComponent(propertiesTableScrollPane);
 
  993         javax.swing.GroupLayout tableContainerPanelLayout = 
new javax.swing.GroupLayout(tableContainerPanel);
 
  994         tableContainerPanel.setLayout(tableContainerPanelLayout);
 
  995         tableContainerPanelLayout.setHorizontalGroup(
 
  996             tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  997             .addGroup(tableContainerPanelLayout.createSequentialGroup()
 
  998                 .addGroup(tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
  999                     .addGroup(tableContainerPanelLayout.createSequentialGroup()
 
 1000                         .addComponent(earliestCaseLabel)
 
 1001                         .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
 1002                         .addComponent(earliestCaseDate)
 
 1004                         .addComponent(foundInLabel))
 
 1005                     .addComponent(jSplitPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 911, Short.MAX_VALUE))
 
 1008         tableContainerPanelLayout.setVerticalGroup(
 
 1009             tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
 1010             .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, tableContainerPanelLayout.createSequentialGroup()
 
 1011                 .addComponent(jSplitPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 31, Short.MAX_VALUE)
 
 1012                 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
 
 1013                 .addGroup(tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
 
 1014                     .addComponent(earliestCaseLabel)
 
 1015                     .addComponent(earliestCaseDate)
 
 1016                     .addComponent(foundInLabel))
 
 1020         javax.swing.GroupLayout otherCasesPanelLayout = 
new javax.swing.GroupLayout(otherCasesPanel);
 
 1021         otherCasesPanel.setLayout(otherCasesPanelLayout);
 
 1022         otherCasesPanelLayout.setHorizontalGroup(
 
 1023             otherCasesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
 1024             .addGap(0, 921, Short.MAX_VALUE)
 
 1025             .addGroup(otherCasesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
 1026                 .addGroup(otherCasesPanelLayout.createSequentialGroup()
 
 1027                     .addComponent(tableContainerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
 
 1030         otherCasesPanelLayout.setVerticalGroup(
 
 1031             otherCasesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
 1032             .addGap(0, 62, Short.MAX_VALUE)
 
 1033             .addGroup(otherCasesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
 1034                 .addGroup(otherCasesPanelLayout.createSequentialGroup()
 
 1035                     .addComponent(tableContainerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 62, Short.MAX_VALUE)
 
 1039         javax.swing.GroupLayout layout = 
new javax.swing.GroupLayout(
this);
 
 1040         this.setLayout(layout);
 
 1041         layout.setHorizontalGroup(
 
 1042             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
 1043             .addComponent(otherCasesPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 1500, Short.MAX_VALUE)
 
 1045         layout.setVerticalGroup(
 
 1046             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
 
 1047             .addComponent(otherCasesPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
 
 1052         boolean enableCentralRepoActions = 
false;
 
 1054         if (
EamDb.
isEnabled() && filesTable.getSelectedRowCount() == 1) {
 
 1055             int rowIndex = filesTable.getSelectedRow();
 
 1056             OtherOccurrenceNodeData selectedNode = (OtherOccurrenceNodeData) tableModel.getRow(rowIndex);
 
 1057             if (selectedNode instanceof OtherOccurrenceNodeInstanceData) {
 
 1058                 OtherOccurrenceNodeInstanceData instanceData = (OtherOccurrenceNodeInstanceData) selectedNode;
 
 1059                 enableCentralRepoActions = instanceData.isCentralRepoNode();
 
 1062         showCaseDetailsMenuItem.setVisible(enableCentralRepoActions);
 
 1063         showCommonalityMenuItem.setVisible(enableCentralRepoActions);
 
 1100             dataSourceID = nodeData.getDeviceID();
 
 1101             if (nodeData.getFilePath() != null) {
 
 1102                 filePath = nodeData.getFilePath().toLowerCase();
 
 1106             type = nodeData.getType();
 
 1112                 UniquePathKey otherKey = (UniquePathKey) (other);
 
 1113                 return (Objects.equals(otherKey.getDataSourceID(), this.getDataSourceID())
 
 1114                         && Objects.equals(otherKey.getFilePath(), this.getFilePath())
 
 1115                         && Objects.equals(otherKey.getType(), this.getType()));
 
 1125             return Objects.hash(getDataSourceID(), getFilePath(), getType());
 
 1142         String getFilePath() {
 
 1151         String getDataSourceID() {
 
 1152             return dataSourceID;
 
void writeSelectedRowsToFileAsCSV(File destFile)
final Collection< CorrelationAttributeInstance > correlationAttributes
void rightClickPopupMenuPopupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt)
static List< CorrelationAttributeInstance > makeInstancesFromBlackboardArtifact(BlackboardArtifact artifact, boolean checkEnabled)
CorrelationCase getCaseByUUID(String caseUUID)
int getFrequencyPercentage(CorrelationAttributeInstance corAttr)
boolean equals(Object other)
String makeDataSourceString(String caseUUID, String deviceId, String dataSourceName)
int isPreferred(Node node)
javax.swing.JLabel earliestCaseLabel
javax.swing.JScrollPane propertiesTableScrollPane
javax.swing.JMenuItem selectAllMenuItem
javax.swing.JMenuItem showCommonalityMenuItem
void updateOnDataSourceSelection()
static CorrelationDataSource fromTSKDataSource(CorrelationCase correlationCase, Content dataSource)
javax.swing.JPanel tableContainerPanel
void setEarliestCaseDate()
String getColumnName(int colIdx)
AbstractFile getAbstractFileFromNode(Node node)
static List< CorrelationAttributeInstance.Type > getDefaultCorrelationTypes()
Object getValueAt(int rowIdx, int colIdx)
javax.swing.JTable dataSourcesTable
Collection< CorrelationAttributeInstance > getCorrelationAttributesFromNode(Node node)
String getCorrelationValue()
final String dataSourceID
List< CorrelationAttributeInstance > getArtifactInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String value)
List< CorrelationAttributeInstance.Type > getDefinedCorrelationTypes()
javax.swing.JPanel otherCasesPanel
final OtherOccurrencesFilesTableModel tableModel
Type getCorrelationType()
void populateTable(Node node)
javax.swing.JPopupMenu rightClickPopupMenu
int getColumnPreferredWidth(int colIdx)
javax.swing.JScrollPane dataSourceScrollPane
javax.swing.JScrollPane caseScrollPane
BlackboardArtifact getBlackboardArtifactFromNode(Node node)
void updateOnCaseSelection()
static EamDb getInstance()
javax.swing.JSplitPane jSplitPane2
boolean isSupported(Node node)
String getCaseDetailsOptionsPaneDialog()
javax.swing.JSplitPane jSplitPane3
void showCaseDetails(int selectedRowViewIdx)
javax.swing.JMenuItem exportToCSVMenuItem
static boolean isEnabled()
SleuthkitCase getSleuthkitCase()
void addOrUpdateNodeData(final Case autopsyCase, Map< UniquePathKey, OtherOccurrenceNodeInstanceData > nodeDataMap, AbstractFile newFile)
void showCommonalityDetails()
DataContentViewerOtherCases()
CorrelationCase getCase(Case autopsyCase)
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)
static boolean isCaseOpen()
javax.swing.JTable casesTable
static final int FILES_TYPE_ID
javax.swing.JMenuItem showCaseDetailsMenuItem
List< CorrelationCase > getCases()