Autopsy  4.11.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
DataContentViewerOtherCases.java
Go to the documentation of this file.
1 /*
2  * Central Repository
3  *
4  * Copyright 2017-2019 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.autopsy.centralrepository.contentviewer;
20 
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;
27 import java.io.File;
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;
40 import java.util.Map;
41 import java.util.Objects;
42 import java.util.Set;
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;
69 import org.sleuthkit.datamodel.AbstractFile;
70 import org.sleuthkit.datamodel.BlackboardArtifact;
71 import org.sleuthkit.datamodel.BlackboardArtifactTag;
72 import org.sleuthkit.datamodel.Content;
73 import org.sleuthkit.datamodel.ContentTag;
74 import org.sleuthkit.datamodel.TskCoreException;
75 import org.sleuthkit.datamodel.TskException;
77 import org.sleuthkit.datamodel.SleuthkitCase;
78 import org.sleuthkit.datamodel.TskData;
79 
83 @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
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."})
89 public class DataContentViewerOtherCases extends JPanel implements DataContentViewer {
90 
91  private static final long serialVersionUID = -1L;
92 
93  private static final Logger LOGGER = Logger.getLogger(DataContentViewerOtherCases.class.getName());
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());
96 
99  private final OtherOccurrencesDataSourcesTableModel dataSourcesTableModel;
100  private OccurrencePanel occurrencePanel;
101  private final Collection<CorrelationAttributeInstance> correlationAttributes;
102  private String dataSourceName = ""; //the data source of the file which the content viewer is being populated for
103  private String deviceId = ""; //the device id of the data source for the file which the content viewer is being populated for
107  private AbstractFile file; //the file which the content viewer is being populated for
108 
113  this.filesTableModel = new OtherOccurrencesFilesTableModel();
114  this.casesTableModel = new OtherOccurrencesCasesTableModel();
115  this.dataSourcesTableModel = new OtherOccurrencesDataSourcesTableModel();
116  this.correlationAttributes = new ArrayList<>();
117  occurrencePanel = new OccurrencePanel();
118  initComponents();
119  customizeComponents();
120 
121  detailsPanelScrollPane.addComponentListener(new ComponentAdapter() {
122  @Override
123  public void componentResized(ComponentEvent componentEvent) {
124  //when its resized make sure the width of the panel resizes to match the scroll pane width to avoid a horizontal scroll bar
125  occurrencePanel.setPreferredSize(new java.awt.Dimension(detailsPanelScrollPane.getPreferredSize().width, occurrencePanel.getPreferredSize().height));
126  detailsPanelScrollPane.setViewportView(occurrencePanel);
127  }
128  });
129  reset();
130  }
131 
132  private void customizeComponents() {
133  ActionListener actList = (ActionEvent e) -> {
134  JMenuItem jmi = (JMenuItem) e.getSource();
135  if (jmi.equals(selectAllMenuItem)) {
136  filesTable.selectAll();
137  } else if (jmi.equals(showCaseDetailsMenuItem)) {
138  showCaseDetails(filesTable.getSelectedRow());
139  } else if (jmi.equals(exportToCSVMenuItem)) {
140  try {
141  saveToCSV();
142  } catch (NoCurrentCaseException ex) {
143  LOGGER.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS
144  }
145  } else if (jmi.equals(showCommonalityMenuItem)) {
146  showCommonalityDetails();
147  }
148  };
149 
150  exportToCSVMenuItem.addActionListener(actList);
151  selectAllMenuItem.addActionListener(actList);
152  showCaseDetailsMenuItem.addActionListener(actList);
153  showCommonalityMenuItem.addActionListener(actList);
154 
155  // Configure column sorting.
156  TableRowSorter<TableModel> sorter = new TableRowSorter<>(filesTable.getModel());
157  filesTable.setRowSorter(sorter);
158  casesTable.getSelectionModel().addListSelectionListener((e) -> {
159  if (Case.isCaseOpen()) {
160  updateOnCaseSelection();
161  }
162  });
163  dataSourcesTable.getSelectionModel().addListSelectionListener((e) -> {
164  if (Case.isCaseOpen()) {
165  updateOnDataSourceSelection();
166  }
167  });
168 
169  //alows resizing of the 4th section
170  filesTable.getSelectionModel().addListSelectionListener((e) -> {
171  if (Case.isCaseOpen()) {
172  occurrencePanel = new OccurrencePanel();
173  updateOnFileSelection();
174  }
175  });
176  //sort tables alphabetically initially
177  casesTable.getRowSorter().toggleSortOrder(0);
178  dataSourcesTable.getRowSorter().toggleSortOrder(0);
179  filesTable.getRowSorter().toggleSortOrder(0);
180  }
181 
182  @Messages({"DataContentViewerOtherCases.correlatedArtifacts.isEmpty=There are no files or artifacts to correlate.",
183  "# {0} - commonality percentage",
184  "# {1} - correlation type",
185  "# {2} - correlation value",
186  "DataContentViewerOtherCases.correlatedArtifacts.byType={0}% of data sources have {2} (type: {1})\n",
187  "DataContentViewerOtherCases.correlatedArtifacts.title=Attribute Frequency",
188  "DataContentViewerOtherCases.correlatedArtifacts.failed=Failed to get frequency details."})
193  private void showCommonalityDetails() {
194  if (correlationAttributes.isEmpty()) {
195  JOptionPane.showConfirmDialog(showCommonalityMenuItem,
196  Bundle.DataContentViewerOtherCases_correlatedArtifacts_isEmpty(),
197  Bundle.DataContentViewerOtherCases_correlatedArtifacts_title(),
198  DEFAULT_OPTION, PLAIN_MESSAGE);
199  } else {
200  StringBuilder msg = new StringBuilder(correlationAttributes.size());
201  int percentage;
202  try {
203  EamDb dbManager = EamDb.getInstance();
204  for (CorrelationAttributeInstance eamArtifact : correlationAttributes) {
205  try {
206  percentage = dbManager.getFrequencyPercentage(eamArtifact);
207  msg.append(Bundle.DataContentViewerOtherCases_correlatedArtifacts_byType(percentage,
208  eamArtifact.getCorrelationType().getDisplayName(),
209  eamArtifact.getCorrelationValue()));
211  LOGGER.log(Level.WARNING, String.format("Error getting commonality details for artifact with ID: %s.", eamArtifact.getID()), ex);
212  }
213  }
214  JOptionPane.showConfirmDialog(showCommonalityMenuItem,
215  msg.toString(),
216  Bundle.DataContentViewerOtherCases_correlatedArtifacts_title(),
217  DEFAULT_OPTION, PLAIN_MESSAGE);
218  } catch (EamDbException ex) {
219  LOGGER.log(Level.SEVERE, "Error getting commonality details.", ex);
220  JOptionPane.showConfirmDialog(showCommonalityMenuItem,
221  Bundle.DataContentViewerOtherCases_correlatedArtifacts_failed(),
222  Bundle.DataContentViewerOtherCases_correlatedArtifacts_title(),
223  DEFAULT_OPTION, ERROR_MESSAGE);
224  }
225  }
226  }
227 
228  @Messages({"DataContentViewerOtherCases.caseDetailsDialog.notSelected=No Row Selected",
229  "DataContentViewerOtherCases.caseDetailsDialog.noDetails=No details for this case.",
230  "DataContentViewerOtherCases.caseDetailsDialog.noDetailsReference=No case details for Global reference properties.",
231  "DataContentViewerOtherCases.caseDetailsDialog.noCaseNameError=Error",
232  "DataContentViewerOtherCases.noOpenCase.errMsg=No open case available."})
233  private void showCaseDetails(int selectedRowViewIdx) {
234  String caseDisplayName = Bundle.DataContentViewerOtherCases_caseDetailsDialog_noCaseNameError();
235  String details = Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetails();
236  try {
237  if (-1 != selectedRowViewIdx) {
238  EamDb dbManager = EamDb.getInstance();
239  int selectedRowModelIdx = filesTable.convertRowIndexToModel(selectedRowViewIdx);
240  List<OtherOccurrenceNodeData> rowList = filesTableModel.getListOfNodesForFile(selectedRowModelIdx);
241  if (!rowList.isEmpty()) {
242  if (rowList.get(0) instanceof OtherOccurrenceNodeInstanceData) {
243  CorrelationCase eamCasePartial = ((OtherOccurrenceNodeInstanceData) rowList.get(0)).getCorrelationAttributeInstance().getCorrelationCase();
244  caseDisplayName = eamCasePartial.getDisplayName();
245  // query case details
246  CorrelationCase eamCase = dbManager.getCaseByUUID(eamCasePartial.getCaseUUID());
247  if (eamCase != null) {
248  details = eamCase.getCaseDetailsOptionsPaneDialog();
249  } else {
250  details = Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetails();
251  }
252  } else {
253  details = Bundle.DataContentViewerOtherCases_caseDetailsDialog_notSelected();
254  }
255  } else {
256  details = Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetailsReference();
257  }
258  }
259  } catch (EamDbException ex) {
260  LOGGER.log(Level.SEVERE, "Error loading case details", ex);
261  } finally {
262  JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
263  details,
264  caseDisplayName,
265  DEFAULT_OPTION, PLAIN_MESSAGE);
266  }
267  }
268 
269  private void saveToCSV() throws NoCurrentCaseException {
270  if (casesTableModel.getRowCount() > 0) {
271  Calendar now = Calendar.getInstance();
272  String fileName = String.format("%1$tY%1$tm%1$te%1$tI%1$tM%1$tS_other_data_sources.csv", now);
273  CSVFileChooser.setCurrentDirectory(new File(Case.getCurrentCaseThrows().getExportDirectory()));
274  CSVFileChooser.setSelectedFile(new File(fileName));
275  CSVFileChooser.setFileFilter(new FileNameExtensionFilter("csv file", "csv"));
276 
277  int returnVal = CSVFileChooser.showSaveDialog(filesTable);
278  if (returnVal == JFileChooser.APPROVE_OPTION) {
279 
280  File selectedFile = CSVFileChooser.getSelectedFile();
281  if (!selectedFile.getName().endsWith(".csv")) { // NON-NLS
282  selectedFile = new File(selectedFile.toString() + ".csv"); // NON-NLS
283  }
284  writeOtherOccurrencesToFileAsCSV(selectedFile);
285  }
286  }
287  }
288 
289  @Messages({
290  "DataContentViewerOtherCasesModel.csvHeader.case=Case",
291  "DataContentViewerOtherCasesModel.csvHeader.device=Device",
292  "DataContentViewerOtherCasesModel.csvHeader.dataSource=Data Source",
293  "DataContentViewerOtherCasesModel.csvHeader.attribute=Matched Attribute",
294  "DataContentViewerOtherCasesModel.csvHeader.value=Attribute Value",
295  "DataContentViewerOtherCasesModel.csvHeader.known=Known",
296  "DataContentViewerOtherCasesModel.csvHeader.path=Path",
297  "DataContentViewerOtherCasesModel.csvHeader.comment=Comment"
298  })
302  private void writeOtherOccurrencesToFileAsCSV(File destFile) {
303  try (BufferedWriter writer = Files.newBufferedWriter(destFile.toPath())) {
304  //write headers
305  StringBuilder headers = new StringBuilder("\"");
306  headers.append(Bundle.DataContentViewerOtherCasesModel_csvHeader_case())
307  .append(OtherOccurrenceNodeInstanceData.getCsvItemSeparator()).append(Bundle.DataContentViewerOtherCasesModel_csvHeader_dataSource())
308  .append(OtherOccurrenceNodeInstanceData.getCsvItemSeparator()).append(Bundle.DataContentViewerOtherCasesModel_csvHeader_attribute())
309  .append(OtherOccurrenceNodeInstanceData.getCsvItemSeparator()).append(Bundle.DataContentViewerOtherCasesModel_csvHeader_value())
310  .append(OtherOccurrenceNodeInstanceData.getCsvItemSeparator()).append(Bundle.DataContentViewerOtherCasesModel_csvHeader_known())
311  .append(OtherOccurrenceNodeInstanceData.getCsvItemSeparator()).append(Bundle.DataContentViewerOtherCasesModel_csvHeader_path())
312  .append(OtherOccurrenceNodeInstanceData.getCsvItemSeparator()).append(Bundle.DataContentViewerOtherCasesModel_csvHeader_comment())
313  .append('"').append(System.getProperty("line.separator"));
314  writer.write(headers.toString());
315  //write content
316  for (CorrelationAttributeInstance corAttr : correlationAttributes) {
317  Map<UniquePathKey, OtherOccurrenceNodeInstanceData> correlatedNodeDataMap = new HashMap<>(0);
318  // get correlation and reference set instances from DB
319  correlatedNodeDataMap.putAll(getCorrelatedInstances(corAttr, dataSourceName, deviceId));
320  for (OtherOccurrenceNodeInstanceData nodeData : correlatedNodeDataMap.values()) {
321  writer.write(nodeData.toCsvString());
322  }
323  }
324  } catch (IOException ex) {
325  LOGGER.log(Level.SEVERE, "Error writing selected rows to CSV.", ex);
326  }
327  }
328 
332  private void reset() {
333  // start with empty table
334  casesTableModel.clearTable();
335  dataSourcesTableModel.clearTable();
336  filesTableModel.clearTable();
337  correlationAttributes.clear();
338  earliestCaseDate.setText(Bundle.DataContentViewerOtherCases_earliestCaseNotAvailable());
339  foundInLabel.setText("");
340  //calling getPreferredSize has a side effect of ensuring it has a preferred size which reflects the contents which are visible
341  occurrencePanel = new OccurrencePanel();
342  occurrencePanel.getPreferredSize();
343  detailsPanelScrollPane.setViewportView(occurrencePanel);
344  }
345 
346  @Override
347  public String getTitle() {
348  return Bundle.DataContentViewerOtherCases_title();
349  }
350 
351  @Override
352  public String getToolTip() {
353  return Bundle.DataContentViewerOtherCases_toolTip();
354  }
355 
356  @Override
358  return new DataContentViewerOtherCases();
359  }
360 
361  @Override
362  public Component getComponent() {
363  return this;
364  }
365 
366  @Override
367  public void resetComponent() {
368  reset();
369  }
370 
371  @Override
372  public int isPreferred(Node node) {
373  return 1;
374 
375  }
376 
384  private BlackboardArtifact
386  BlackboardArtifactTag nodeBbArtifactTag = node.getLookup().lookup(BlackboardArtifactTag.class
387  );
388  BlackboardArtifact nodeBbArtifact = node.getLookup().lookup(BlackboardArtifact.class
389  );
390 
391  if (nodeBbArtifactTag != null) {
392  return nodeBbArtifactTag.getArtifact();
393  } else if (nodeBbArtifact != null) {
394  return nodeBbArtifact;
395  }
396 
397  return null;
398 
399  }
400 
408  private AbstractFile getAbstractFileFromNode(Node node) {
409  BlackboardArtifactTag nodeBbArtifactTag = node.getLookup().lookup(BlackboardArtifactTag.class
410  );
411  ContentTag nodeContentTag = node.getLookup().lookup(ContentTag.class
412  );
413  BlackboardArtifact nodeBbArtifact = node.getLookup().lookup(BlackboardArtifact.class
414  );
415  AbstractFile nodeAbstractFile = node.getLookup().lookup(AbstractFile.class
416  );
417 
418  if (nodeBbArtifactTag != null) {
419  Content content = nodeBbArtifactTag.getContent();
420  if (content instanceof AbstractFile) {
421  return (AbstractFile) content;
422  }
423  } else if (nodeContentTag != null) {
424  Content content = nodeContentTag.getContent();
425  if (content instanceof AbstractFile) {
426  return (AbstractFile) content;
427  }
428  } else if (nodeBbArtifact != null) {
429  Content content;
430  try {
431  content = nodeBbArtifact.getSleuthkitCase().getContentById(nodeBbArtifact.getObjectID());
432  } catch (TskCoreException ex) {
433  LOGGER.log(Level.SEVERE, "Error retrieving blackboard artifact", ex); // NON-NLS
434  return null;
435  }
436 
437  if (content instanceof AbstractFile) {
438  return (AbstractFile) content;
439  }
440  } else if (nodeAbstractFile != null) {
441  return nodeAbstractFile;
442  }
443 
444  return null;
445  }
446 
455  private Collection<CorrelationAttributeInstance> getCorrelationAttributesFromNode(Node node) {
456  Collection<CorrelationAttributeInstance> ret = new ArrayList<>();
457 
458  // correlate on blackboard artifact attributes if they exist and supported
459  BlackboardArtifact bbArtifact = getBlackboardArtifactFromNode(node);
460  if (bbArtifact != null && EamDb.isEnabled()) {
461  ret.addAll(EamArtifactUtil.makeInstancesFromBlackboardArtifact(bbArtifact, false));
462  }
463 
464  // we can correlate based on the MD5 if it is enabled
465  if (this.file != null && EamDb.isEnabled() && this.file.getSize() > 0) {
466  try {
467 
469  String md5 = this.file.getMd5Hash();
470  if (md5 != null && !md5.isEmpty() && null != artifactTypes && !artifactTypes.isEmpty()) {
471  for (CorrelationAttributeInstance.Type aType : artifactTypes) {
472  if (aType.getId() == CorrelationAttributeInstance.FILES_TYPE_ID) {
474  try {
475  ret.add(new CorrelationAttributeInstance(
476  aType,
477  md5,
478  corCase,
479  CorrelationDataSource.fromTSKDataSource(corCase, file.getDataSource()),
480  file.getParentPath() + file.getName(),
481  "",
482  file.getKnown(),
483  file.getId()));
485  LOGGER.log(Level.INFO, String.format("Unable to check create CorrelationAttribtueInstance for value %s and type %s.", md5, aType.toString()), ex);
486  }
487  break;
488  }
489  }
490  }
491  } catch (EamDbException | TskCoreException ex) {
492  LOGGER.log(Level.SEVERE, "Error connecting to DB", ex); // NON-NLS
493  }
494  // If EamDb not enabled, get the Files default correlation type to allow Other Occurances to be enabled.
495  } else if (this.file != null && this.file.getSize() > 0) {
496  String md5 = this.file.getMd5Hash();
497  if (md5 != null && !md5.isEmpty()) {
498  try {
499  final CorrelationAttributeInstance.Type fileAttributeType
501  .stream()
502  .filter(attrType -> attrType.getId() == CorrelationAttributeInstance.FILES_TYPE_ID)
503  .findAny()
504  .get();
505  //The Central Repository is not enabled
506  ret.add(new CorrelationAttributeInstance(fileAttributeType, md5, null, null, "", "", TskData.FileKnown.UNKNOWN, this.file.getId()));
507  } catch (EamDbException ex) {
508  LOGGER.log(Level.SEVERE, "Error connecting to DB", ex); // NON-NLS
510  LOGGER.log(Level.INFO, String.format("Unable to create CorrelationAttributeInstance for value %s", md5), ex); // NON-NLS
511  }
512  }
513  }
514 
515  return ret;
516  }
517 
518  @Messages({"DataContentViewerOtherCases.earliestCaseNotAvailable= Not Enabled."})
523  private void setEarliestCaseDate() {
524  String dateStringDisplay = Bundle.DataContentViewerOtherCases_earliestCaseNotAvailable();
525 
526  if (EamDb.isEnabled()) {
527  LocalDateTime earliestDate = LocalDateTime.now(DateTimeZone.UTC);
528  DateFormat datetimeFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss", Locale.US);
529  try {
530  EamDb dbManager = EamDb.getInstance();
531  List<CorrelationCase> cases = dbManager.getCases();
532  for (CorrelationCase aCase : cases) {
533  LocalDateTime caseDate = LocalDateTime.fromDateFields(datetimeFormat.parse(aCase.getCreationDate()));
534 
535  if (caseDate.isBefore(earliestDate)) {
536  earliestDate = caseDate;
537  dateStringDisplay = aCase.getCreationDate();
538  }
539 
540  }
541 
542  } catch (EamDbException ex) {
543  LOGGER.log(Level.SEVERE, "Error getting list of cases from database.", ex); // NON-NLS
544  } catch (ParseException ex) {
545  LOGGER.log(Level.SEVERE, "Error parsing date of cases from database.", ex); // NON-NLS
546  }
547 
548  }
549  earliestCaseDate.setText(dateStringDisplay);
550  }
551 
564  private Map<UniquePathKey, OtherOccurrenceNodeInstanceData> getCorrelatedInstances(CorrelationAttributeInstance corAttr, String dataSourceName, String deviceId) {
565  // @@@ Check exception
566  try {
567  final Case openCase = Case.getCurrentCaseThrows();
568  String caseUUID = openCase.getName();
569  HashMap<UniquePathKey, OtherOccurrenceNodeInstanceData> nodeDataMap = new HashMap<>();
570 
571  if (EamDb.isEnabled()) {
572  List<CorrelationAttributeInstance> instances = EamDb.getInstance().getArtifactInstancesByTypeValue(corAttr.getCorrelationType(), corAttr.getCorrelationValue());
573 
574  for (CorrelationAttributeInstance artifactInstance : instances) {
575 
576  // Only add the attribute if it isn't the object the user selected.
577  // We consider it to be a different object if at least one of the following is true:
578  // - the case UUID is different
579  // - the data source name is different
580  // - the data source device ID is different
581  // - the file path is different
582  if (!artifactInstance.getCorrelationCase().getCaseUUID().equals(caseUUID)
583  || !artifactInstance.getCorrelationDataSource().getName().equals(dataSourceName)
584  || !artifactInstance.getCorrelationDataSource().getDeviceID().equals(deviceId)
585  || !artifactInstance.getFilePath().equalsIgnoreCase(file.getParentPath() + file.getName())) {
586 
587  OtherOccurrenceNodeInstanceData newNode = new OtherOccurrenceNodeInstanceData(artifactInstance, corAttr.getCorrelationType(), corAttr.getCorrelationValue());
588  UniquePathKey uniquePathKey = new UniquePathKey(newNode);
589  nodeDataMap.put(uniquePathKey, newNode);
590  }
591  }
592  }
593  if (corAttr.getCorrelationType().getDisplayName().equals("Files")) {
594  List<AbstractFile> caseDbFiles = getCaseDbMatches(corAttr, openCase);
595 
596  for (AbstractFile caseDbFile : caseDbFiles) {
597  addOrUpdateNodeData(openCase, nodeDataMap, caseDbFile);
598  }
599  }
600  return nodeDataMap;
601  } catch (EamDbException ex) {
602  LOGGER.log(Level.SEVERE, "Error getting artifact instances from database.", ex); // NON-NLS
604  LOGGER.log(Level.INFO, "Error getting artifact instances from database.", ex); // NON-NLS
605  } catch (NoCurrentCaseException ex) {
606  LOGGER.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS
607  } catch (TskCoreException ex) {
608  // do nothing.
609  // @@@ Review this behavior
610  LOGGER.log(Level.SEVERE, "Exception while querying open case.", ex); // NON-NLS
611  }
612 
613  return new HashMap<>(0);
614  }
615 
629  private List<AbstractFile> getCaseDbMatches(CorrelationAttributeInstance corAttr, Case openCase) throws NoCurrentCaseException, TskCoreException, EamDbException {
630  String md5 = corAttr.getCorrelationValue();
631  SleuthkitCase tsk = openCase.getSleuthkitCase();
632  List<AbstractFile> matches = tsk.findAllFilesWhere(String.format("md5 = '%s'", new Object[]{md5}));
633 
634  List<AbstractFile> caseDbArtifactInstances = new ArrayList<>();
635  for (AbstractFile fileMatch : matches) {
636  if (this.file.equals(fileMatch)) {
637  continue; // If this is the file the user clicked on
638  }
639  caseDbArtifactInstances.add(fileMatch);
640  }
641  return caseDbArtifactInstances;
642 
643  }
644 
655  private void addOrUpdateNodeData(final Case autopsyCase, Map<UniquePathKey, OtherOccurrenceNodeInstanceData> nodeDataMap, AbstractFile newFile) throws TskCoreException, EamDbException {
656 
657  OtherOccurrenceNodeInstanceData newNode = new OtherOccurrenceNodeInstanceData(newFile, autopsyCase);
658 
659  // If the caseDB object has a notable tag associated with it, update
660  // the known status to BAD
661  if (newNode.getKnown() != TskData.FileKnown.BAD) {
662  List<ContentTag> fileMatchTags = autopsyCase.getServices().getTagsManager().getContentTagsByContent(newFile);
663  for (ContentTag tag : fileMatchTags) {
664  TskData.FileKnown tagKnownStatus = tag.getName().getKnownStatus();
665  if (tagKnownStatus.equals(TskData.FileKnown.BAD)) {
666  newNode.updateKnown(TskData.FileKnown.BAD);
667  break;
668  }
669  }
670  }
671 
672  // Make a key to see if the file is already in the map
673  UniquePathKey uniquePathKey = new UniquePathKey(newNode);
674 
675  // If this node is already in the list, the only thing we need to do is
676  // update the known status to BAD if the caseDB version had known status BAD.
677  // Otherwise this is a new node so add the new node to the map.
678  if (nodeDataMap.containsKey(uniquePathKey)) {
679  if (newNode.getKnown() == TskData.FileKnown.BAD) {
680  OtherOccurrenceNodeInstanceData prevInstance = nodeDataMap.get(uniquePathKey);
681  prevInstance.updateKnown(newNode.getKnown());
682  }
683  } else {
684  nodeDataMap.put(uniquePathKey, newNode);
685  }
686  }
687 
688  @Override
689  public boolean isSupported(Node node) {
690 
691  // Is supported if one of the following is true:
692  // - The central repo is enabled and the node has correlatable content
693  // (either through the MD5 hash of the associated file or through a BlackboardArtifact)
694  // - The central repo is disabled and the backing file has a valid MD5 hash
695  this.file = this.getAbstractFileFromNode(node);
696  if (EamDb.isEnabled()) {
697  return !getCorrelationAttributesFromNode(node).isEmpty();
698  } else {
699  return this.file != null
700  && this.file.getSize() > 0
701  && ((this.file.getMd5Hash() != null) && (!this.file.getMd5Hash().isEmpty()));
702  }
703  }
704 
705  @Override
706  public void setNode(Node node) {
707 
708  reset(); // reset the table to empty.
709  if (node == null) {
710  return;
711  }
712  //could be null
713  this.file = this.getAbstractFileFromNode(node);
714  populateTable(node);
715 
716  }
717 
724  @Messages({
725  "DataContentViewerOtherCases.dataSources.header.text=Data Source Name",
726  "DataContentViewerOtherCases.foundIn.text=Found %d instances in %d cases and %d data sources."
727  })
728  private void populateTable(Node node) {
729  try {
730  if (this.file != null) {
731  Content dataSource = this.file.getDataSource();
732  dataSourceName = dataSource.getName();
733  deviceId = Case.getCurrentCaseThrows().getSleuthkitCase().getDataSource(dataSource.getId()).getDeviceId();
734  }
735  } catch (TskException | NoCurrentCaseException ex) {
736  // do nothing.
737  // @@@ Review this behavior
738  }
739 
740  // get the attributes we can correlate on
741  correlationAttributes.addAll(getCorrelationAttributesFromNode(node));
742  Map<String, CorrelationCase> caseNames = new HashMap<>();
743  int totalCount = 0;
744  Set<String> dataSources = new HashSet<>();
745  for (CorrelationAttributeInstance corAttr : correlationAttributes) {
746  Map<UniquePathKey, OtherOccurrenceNodeInstanceData> correlatedNodeDataMap = new HashMap<>(0);
747 
748  // get correlation and reference set instances from DB
749  correlatedNodeDataMap.putAll(getCorrelatedInstances(corAttr, dataSourceName, deviceId));
750  for (OtherOccurrenceNodeInstanceData nodeData : correlatedNodeDataMap.values()) {
751  if (nodeData.isCentralRepoNode()) {
752  try {
753  dataSources.add(makeDataSourceString(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID(), nodeData.getDeviceID(), nodeData.getDataSourceName()));
754  caseNames.put(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID(), nodeData.getCorrelationAttributeInstance().getCorrelationCase());
755  } catch (EamDbException ex) {
756  LOGGER.log(Level.WARNING, "Unable to get correlation case for displaying other occurrence for case: " + nodeData.getCaseName(), ex);
757  }
758  } else {
759  try {
760  dataSources.add(makeDataSourceString(Case.getCurrentCaseThrows().getName(), nodeData.getDeviceID(), nodeData.getDataSourceName()));
762  } catch (NoCurrentCaseException ex) {
763  LOGGER.log(Level.WARNING, "No current case open for other occurrences", ex);
764  }
765  }
766  totalCount++;
767  }
768  }
769  for (CorrelationCase corCase : caseNames.values()) {
770  casesTableModel.addCorrelationCase(new CorrelationCaseWrapper(corCase));
771  }
772  int caseCount = casesTableModel.getRowCount();
773  if (correlationAttributes.isEmpty()) {
774  casesTableModel.addCorrelationCase(NO_ARTIFACTS_CASE);
775  } else if (caseCount == 0) {
776  casesTableModel.addCorrelationCase(NO_RESULTS_CASE);
777  }
778  setEarliestCaseDate();
779  foundInLabel.setText(String.format(Bundle.DataContentViewerOtherCases_foundIn_text(), totalCount, caseCount, dataSources.size()));
780  if (caseCount > 0) {
781  casesTable.setRowSelectionInterval(0, 0);
782  }
783  }
784 
789  private String makeDataSourceString(String caseUUID, String deviceId, String dataSourceName) {
790  return caseUUID + deviceId + dataSourceName;
791  }
792 
796  private void updateOnCaseSelection() {
797  int[] selectedCaseIndexes = casesTable.getSelectedRows();
798  dataSourcesTableModel.clearTable();
799  filesTableModel.clearTable();
800 
801  if (selectedCaseIndexes.length == 0) {
802  //special case when no cases are selected
803  occurrencePanel = new OccurrencePanel();
804  occurrencePanel.getPreferredSize();
805  detailsPanelScrollPane.setViewportView(occurrencePanel);
806  } else {
807  for (CorrelationAttributeInstance corAttr : correlationAttributes) {
808  Map<UniquePathKey, OtherOccurrenceNodeInstanceData> correlatedNodeDataMap = new HashMap<>(0);
809 
810  // get correlation and reference set instances from DB
811  correlatedNodeDataMap.putAll(getCorrelatedInstances(corAttr, dataSourceName, deviceId));
812  for (OtherOccurrenceNodeInstanceData nodeData : correlatedNodeDataMap.values()) {
813  for (int selectedRow : selectedCaseIndexes) {
814  try {
815  if (nodeData.isCentralRepoNode()) {
816  if (casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedRow)) != null
817  && casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedRow)).getCaseUUID().equals(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID())) {
818  dataSourcesTableModel.addNodeData(nodeData);
819  }
820  } else {
821  dataSourcesTableModel.addNodeData(nodeData);
822  }
823  } catch (EamDbException ex) {
824  LOGGER.log(Level.WARNING, "Unable to get correlation attribute instance from OtherOccurrenceNodeInstanceData for case " + nodeData.getCaseName(), ex);
825  }
826  }
827  }
828  }
829  if (dataSourcesTable.getRowCount() > 0) {
830  dataSourcesTable.setRowSelectionInterval(0, 0);
831  }
832  }
833  }
834 
840  int[] selectedCaseIndexes = casesTable.getSelectedRows();
841  int[] selectedDataSources = dataSourcesTable.getSelectedRows();
842  filesTableModel.clearTable();
843  for (CorrelationAttributeInstance corAttr : correlationAttributes) {
844  Map<UniquePathKey, OtherOccurrenceNodeInstanceData> correlatedNodeDataMap = new HashMap<>(0);
845 
846  // get correlation and reference set instances from DB
847  correlatedNodeDataMap.putAll(getCorrelatedInstances(corAttr, dataSourceName, deviceId));
848  for (OtherOccurrenceNodeInstanceData nodeData : correlatedNodeDataMap.values()) {
849  for (int selectedCaseRow : selectedCaseIndexes) {
850  for (int selectedDataSourceRow : selectedDataSources) {
851  try {
852  if (nodeData.isCentralRepoNode()) {
853  if (casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedCaseRow)) != null
854  && casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedCaseRow)).getCaseUUID().equals(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID())
855  && dataSourcesTableModel.getDeviceIdForRow(dataSourcesTable.convertRowIndexToModel(selectedDataSourceRow)).equals(nodeData.getDeviceID())) {
856  filesTableModel.addNodeData(nodeData);
857  }
858  } else {
859  if (dataSourcesTableModel.getDeviceIdForRow(dataSourcesTable.convertRowIndexToModel(selectedDataSourceRow)).equals(nodeData.getDeviceID())) {
860  filesTableModel.addNodeData(nodeData);
861  }
862  }
863  } catch (EamDbException ex) {
864  LOGGER.log(Level.WARNING, "Unable to get correlation attribute instance from OtherOccurrenceNodeInstanceData for case " + nodeData.getCaseName(), ex);
865  }
866  }
867  }
868  }
869  }
870  if (filesTable.getRowCount() > 0) {
871  filesTable.setRowSelectionInterval(0, 0);
872  }
873  }
874 
879  private void updateOnFileSelection() {
880  if (filesTable.getSelectedRowCount() == 1) {
881  //if there is one file selected update the deatils to show the data for that file
882  occurrencePanel = new OccurrencePanel(filesTableModel.getListOfNodesForFile(filesTable.convertRowIndexToModel(filesTable.getSelectedRow())));
883  } else if (dataSourcesTable.getSelectedRowCount() == 1) {
884  //if no files were selected and only one data source is selected update the information to reflect the data source
885  String caseName = dataSourcesTableModel.getCaseNameForRow(dataSourcesTable.convertRowIndexToModel(dataSourcesTable.getSelectedRow()));
886  String dsName = dataSourcesTableModel.getValueAt(dataSourcesTable.convertRowIndexToModel(dataSourcesTable.getSelectedRow()), 0).toString();
887  String caseCreatedDate = "";
888  for (int row : casesTable.getSelectedRows()) {
889  if (casesTableModel.getValueAt(casesTable.convertRowIndexToModel(row), 0).toString().equals(caseName)) {
890  caseCreatedDate = getCaseCreatedDate(row);
891  break;
892  }
893  }
894  occurrencePanel = new OccurrencePanel(caseName, caseCreatedDate, dsName);
895  } else if (casesTable.getSelectedRowCount() == 1) {
896  //if no files were selected and a number of data source other than 1 are selected
897  //update the information to reflect the case
898  String createdDate = "";
899  String caseName = "";
900  if (casesTable.getRowCount() > 0) {
901  caseName = casesTableModel.getValueAt(casesTable.convertRowIndexToModel(casesTable.getSelectedRow()), 0).toString();
902  }
903  if (caseName.isEmpty()) {
904  occurrencePanel = new OccurrencePanel();
905  } else {
906  createdDate = getCaseCreatedDate(casesTable.getSelectedRow());
907  occurrencePanel = new OccurrencePanel(caseName, createdDate);
908  }
909  } else {
910  //else display an empty details area
911  occurrencePanel = new OccurrencePanel();
912  }
913  //calling getPreferredSize has a side effect of ensuring it has a preferred size which reflects the contents which are visible
914  occurrencePanel.getPreferredSize();
915  detailsPanelScrollPane.setViewportView(occurrencePanel);
916  }
917 
926  private String getCaseCreatedDate(int caseTableRowIdx) {
927  try {
928  if (EamDb.isEnabled()) {
929  CorrelationCase partialCase;
930  partialCase = casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(caseTableRowIdx));
931  if (partialCase == null){
932  return "";
933  }
934  return EamDb.getInstance().getCaseByUUID(partialCase.getCaseUUID()).getCreationDate();
935  } else {
937  }
938  } catch (EamDbException ex) {
939  LOGGER.log(Level.WARNING, "Error getting case created date for row: " + caseTableRowIdx, ex);
940  }
941  return "";
942  }
943 
949  @SuppressWarnings("unchecked")
950  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
951  private void initComponents() {
952 
953  rightClickPopupMenu = new javax.swing.JPopupMenu();
954  selectAllMenuItem = new javax.swing.JMenuItem();
955  exportToCSVMenuItem = new javax.swing.JMenuItem();
956  showCaseDetailsMenuItem = new javax.swing.JMenuItem();
957  showCommonalityMenuItem = new javax.swing.JMenuItem();
958  CSVFileChooser = new javax.swing.JFileChooser();
959  tableContainerPanel = new javax.swing.JPanel();
960  earliestCaseLabel = new javax.swing.JLabel();
961  earliestCaseDate = new javax.swing.JLabel();
962  foundInLabel = new javax.swing.JLabel();
963  tablesViewerSplitPane = new javax.swing.JSplitPane();
964  caseDatasourceFileSplitPane = new javax.swing.JSplitPane();
965  caseDatasourceSplitPane = new javax.swing.JSplitPane();
966  caseScrollPane = new javax.swing.JScrollPane();
967  casesTable = new javax.swing.JTable();
968  dataSourceScrollPane = new javax.swing.JScrollPane();
969  dataSourcesTable = new javax.swing.JTable();
970  filesTableScrollPane = new javax.swing.JScrollPane();
971  filesTable = new javax.swing.JTable();
972  detailsPanelScrollPane = new javax.swing.JScrollPane();
973 
974  rightClickPopupMenu.addPopupMenuListener(new javax.swing.event.PopupMenuListener() {
975  public void popupMenuCanceled(javax.swing.event.PopupMenuEvent evt) {
976  }
977  public void popupMenuWillBecomeInvisible(javax.swing.event.PopupMenuEvent evt) {
978  }
979  public void popupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt) {
980  rightClickPopupMenuPopupMenuWillBecomeVisible(evt);
981  }
982  });
983 
984  org.openide.awt.Mnemonics.setLocalizedText(selectAllMenuItem, org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.selectAllMenuItem.text")); // NOI18N
985  rightClickPopupMenu.add(selectAllMenuItem);
986 
987  org.openide.awt.Mnemonics.setLocalizedText(exportToCSVMenuItem, org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.exportToCSVMenuItem.text")); // NOI18N
988  rightClickPopupMenu.add(exportToCSVMenuItem);
989 
990  org.openide.awt.Mnemonics.setLocalizedText(showCaseDetailsMenuItem, org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.showCaseDetailsMenuItem.text")); // NOI18N
991  rightClickPopupMenu.add(showCaseDetailsMenuItem);
992 
993  org.openide.awt.Mnemonics.setLocalizedText(showCommonalityMenuItem, org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.showCommonalityMenuItem.text")); // NOI18N
994  rightClickPopupMenu.add(showCommonalityMenuItem);
995 
996  setMinimumSize(new java.awt.Dimension(600, 10));
997  setOpaque(false);
998  setPreferredSize(new java.awt.Dimension(600, 63));
999 
1000  tableContainerPanel.setPreferredSize(new java.awt.Dimension(600, 63));
1001  tableContainerPanel.setRequestFocusEnabled(false);
1002 
1003  org.openide.awt.Mnemonics.setLocalizedText(earliestCaseLabel, org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.earliestCaseLabel.text")); // NOI18N
1004  earliestCaseLabel.setToolTipText(org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.earliestCaseLabel.toolTipText")); // NOI18N
1005 
1006  org.openide.awt.Mnemonics.setLocalizedText(earliestCaseDate, org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.earliestCaseDate.text")); // NOI18N
1007 
1008  org.openide.awt.Mnemonics.setLocalizedText(foundInLabel, org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.foundInLabel.text")); // NOI18N
1009 
1010  tablesViewerSplitPane.setDividerLocation(450);
1011  tablesViewerSplitPane.setResizeWeight(0.75);
1012 
1013  caseDatasourceFileSplitPane.setDividerLocation(300);
1014  caseDatasourceFileSplitPane.setResizeWeight(0.66);
1015  caseDatasourceFileSplitPane.setToolTipText("");
1016 
1017  caseDatasourceSplitPane.setDividerLocation(150);
1018  caseDatasourceSplitPane.setResizeWeight(0.5);
1019 
1020  caseScrollPane.setPreferredSize(new java.awt.Dimension(150, 30));
1021 
1022  casesTable.setAutoCreateRowSorter(true);
1023  casesTable.setModel(casesTableModel);
1024  caseScrollPane.setViewportView(casesTable);
1025 
1026  caseDatasourceSplitPane.setLeftComponent(caseScrollPane);
1027 
1028  dataSourceScrollPane.setPreferredSize(new java.awt.Dimension(150, 30));
1029 
1030  dataSourcesTable.setAutoCreateRowSorter(true);
1031  dataSourcesTable.setModel(dataSourcesTableModel);
1032  dataSourceScrollPane.setViewportView(dataSourcesTable);
1033 
1034  caseDatasourceSplitPane.setRightComponent(dataSourceScrollPane);
1035 
1036  caseDatasourceFileSplitPane.setLeftComponent(caseDatasourceSplitPane);
1037 
1038  filesTableScrollPane.setPreferredSize(new java.awt.Dimension(150, 30));
1039 
1040  filesTable.setAutoCreateRowSorter(true);
1041  filesTable.setModel(filesTableModel);
1042  filesTable.setToolTipText(org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.table.toolTip.text")); // NOI18N
1043  filesTable.setComponentPopupMenu(rightClickPopupMenu);
1044  filesTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
1045  filesTableScrollPane.setViewportView(filesTable);
1046 
1047  caseDatasourceFileSplitPane.setRightComponent(filesTableScrollPane);
1048 
1049  tablesViewerSplitPane.setLeftComponent(caseDatasourceFileSplitPane);
1050 
1051  detailsPanelScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
1052  detailsPanelScrollPane.setPreferredSize(new java.awt.Dimension(300, 100));
1053  tablesViewerSplitPane.setRightComponent(detailsPanelScrollPane);
1054 
1055  javax.swing.GroupLayout tableContainerPanelLayout = new javax.swing.GroupLayout(tableContainerPanel);
1056  tableContainerPanel.setLayout(tableContainerPanelLayout);
1057  tableContainerPanelLayout.setHorizontalGroup(
1058  tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
1059  .addGroup(tableContainerPanelLayout.createSequentialGroup()
1060  .addGroup(tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
1061  .addGroup(tableContainerPanelLayout.createSequentialGroup()
1062  .addComponent(earliestCaseLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 161, javax.swing.GroupLayout.PREFERRED_SIZE)
1063  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
1064  .addComponent(earliestCaseDate, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
1065  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
1066  .addComponent(foundInLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
1067  .addComponent(tablesViewerSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 765, Short.MAX_VALUE))
1068  .addContainerGap())
1069  );
1070  tableContainerPanelLayout.setVerticalGroup(
1071  tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
1072  .addGroup(tableContainerPanelLayout.createSequentialGroup()
1073  .addGap(0, 0, 0)
1074  .addComponent(tablesViewerSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 33, Short.MAX_VALUE)
1075  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
1076  .addGroup(tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
1077  .addGroup(tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
1078  .addComponent(earliestCaseLabel)
1079  .addComponent(earliestCaseDate))
1080  .addComponent(foundInLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE))
1081  .addContainerGap())
1082  );
1083 
1084  javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
1085  this.setLayout(layout);
1086  layout.setHorizontalGroup(
1087  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
1088  .addComponent(tableContainerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 775, Short.MAX_VALUE)
1089  );
1090  layout.setVerticalGroup(
1091  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
1092  .addGroup(layout.createSequentialGroup()
1093  .addComponent(tableContainerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 64, Short.MAX_VALUE)
1094  .addGap(0, 0, 0))
1095  );
1096  }// </editor-fold>//GEN-END:initComponents
1097 
1098  private void rightClickPopupMenuPopupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt) {//GEN-FIRST:event_rightClickPopupMenuPopupMenuWillBecomeVisible
1099  boolean enableCentralRepoActions = false;
1100  if (EamDb.isEnabled() && filesTable.getSelectedRowCount() == 1) {
1101  int rowIndex = filesTable.getSelectedRow();
1102  List<OtherOccurrenceNodeData> selectedFile = filesTableModel.getListOfNodesForFile(rowIndex);
1103  if (!selectedFile.isEmpty() && selectedFile.get(0) instanceof OtherOccurrenceNodeInstanceData) {
1104  OtherOccurrenceNodeInstanceData instanceData = (OtherOccurrenceNodeInstanceData) selectedFile.get(0);
1105  enableCentralRepoActions = instanceData.isCentralRepoNode();
1106  }
1107  }
1108  showCaseDetailsMenuItem.setVisible(enableCentralRepoActions);
1109  showCommonalityMenuItem.setVisible(enableCentralRepoActions);
1110  }//GEN-LAST:event_rightClickPopupMenuPopupMenuWillBecomeVisible
1111 
1112  // Variables declaration - do not modify//GEN-BEGIN:variables
1113  private javax.swing.JFileChooser CSVFileChooser;
1114  private javax.swing.JSplitPane caseDatasourceFileSplitPane;
1115  private javax.swing.JSplitPane caseDatasourceSplitPane;
1116  private javax.swing.JScrollPane caseScrollPane;
1117  private javax.swing.JTable casesTable;
1118  private javax.swing.JScrollPane dataSourceScrollPane;
1119  private javax.swing.JTable dataSourcesTable;
1120  private javax.swing.JScrollPane detailsPanelScrollPane;
1121  private javax.swing.JLabel earliestCaseDate;
1122  private javax.swing.JLabel earliestCaseLabel;
1123  private javax.swing.JMenuItem exportToCSVMenuItem;
1124  private javax.swing.JTable filesTable;
1125  private javax.swing.JScrollPane filesTableScrollPane;
1126  private javax.swing.JLabel foundInLabel;
1127  private javax.swing.JPopupMenu rightClickPopupMenu;
1128  private javax.swing.JMenuItem selectAllMenuItem;
1129  private javax.swing.JMenuItem showCaseDetailsMenuItem;
1130  private javax.swing.JMenuItem showCommonalityMenuItem;
1131  private javax.swing.JPanel tableContainerPanel;
1132  private javax.swing.JSplitPane tablesViewerSplitPane;
1133  // End of variables declaration//GEN-END:variables
1134 
1139  private static final class UniquePathKey {
1140 
1141  private final String dataSourceID;
1142  private final String filePath;
1143  private final String type;
1144 
1145  UniquePathKey(OtherOccurrenceNodeInstanceData nodeData) {
1146  super();
1147  dataSourceID = nodeData.getDeviceID();
1148  if (nodeData.getFilePath() != null) {
1149  filePath = nodeData.getFilePath().toLowerCase();
1150  } else {
1151  filePath = null;
1152  }
1153  type = nodeData.getType();
1154  }
1155 
1156  @Override
1157  public boolean equals(Object other) {
1158  if (other instanceof UniquePathKey) {
1159  UniquePathKey otherKey = (UniquePathKey) (other);
1160  return (Objects.equals(otherKey.getDataSourceID(), this.getDataSourceID())
1161  && Objects.equals(otherKey.getFilePath(), this.getFilePath())
1162  && Objects.equals(otherKey.getType(), this.getType()));
1163  }
1164  return false;
1165  }
1166 
1167  @Override
1168  public int hashCode() {
1169  return Objects.hash(getDataSourceID(), getFilePath(), getType());
1170  }
1171 
1177  String getType() {
1178  return type;
1179  }
1180 
1186  String getFilePath() {
1187  return filePath;
1188  }
1189 
1195  String getDataSourceID() {
1196  return dataSourceID;
1197  }
1198  }
1199 }
static List< CorrelationAttributeInstance > makeInstancesFromBlackboardArtifact(BlackboardArtifact artifact, boolean checkEnabled)
CorrelationCase getCaseByUUID(String caseUUID)
int getFrequencyPercentage(CorrelationAttributeInstance corAttr)
String makeDataSourceString(String caseUUID, String deviceId, String dataSourceName)
static CorrelationDataSource fromTSKDataSource(CorrelationCase correlationCase, Content dataSource)
List< CorrelationAttributeInstance > getArtifactInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String value)
List< CorrelationAttributeInstance.Type > getDefinedCorrelationTypes()
void addOrUpdateNodeData(final Case autopsyCase, Map< UniquePathKey, OtherOccurrenceNodeInstanceData > nodeDataMap, AbstractFile newFile)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
List< AbstractFile > getCaseDbMatches(CorrelationAttributeInstance corAttr, Case openCase)
Map< UniquePathKey, OtherOccurrenceNodeInstanceData > getCorrelatedInstances(CorrelationAttributeInstance corAttr, String dataSourceName, String deviceId)

Copyright © 2012-2018 Basis Technology. Generated on: Fri Jun 21 2019
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.