Autopsy  4.10.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 2015-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.io.BufferedWriter;
25 import java.io.File;
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;
38 import java.util.Map;
39 import java.util.Objects;
40 import java.util.Set;
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;
70 import org.sleuthkit.datamodel.AbstractFile;
71 import org.sleuthkit.datamodel.BlackboardArtifact;
72 import org.sleuthkit.datamodel.BlackboardArtifactTag;
73 import org.sleuthkit.datamodel.Content;
74 import org.sleuthkit.datamodel.ContentTag;
75 import org.sleuthkit.datamodel.TskCoreException;
76 import org.sleuthkit.datamodel.TskException;
78 import org.sleuthkit.datamodel.SleuthkitCase;
79 import org.sleuthkit.datamodel.TskData;
80 
84 @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
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."})
90 public class DataContentViewerOtherCases extends JPanel implements DataContentViewer {
91 
92  private static final long serialVersionUID = -1L;
93 
94  private static final Logger LOGGER = Logger.getLogger(DataContentViewerOtherCases.class.getName());
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;
98 
101  private final Collection<CorrelationAttributeInstance> correlationAttributes;
102  private String dataSourceName = "";
103  private String deviceId = "";
107  private AbstractFile file;
108 
113  this.tableModel = new OtherOccurrencesFilesTableModel();
114  this.casesTableModel = new OtherOccurrencesCasesTableModel();
115  this.correlationAttributes = new ArrayList<>();
116 
117  initComponents();
118  customizeComponents();
119  reset();
120  }
121 
122  private void customizeComponents() {
123  ActionListener actList = new ActionListener() {
124  @Override
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)) {
132  try {
133  saveToCSV();
134  } catch (NoCurrentCaseException ex) {
135  LOGGER.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS
136  }
137  } else if (jmi.equals(showCommonalityMenuItem)) {
138  showCommonalityDetails();
139  }
140  }
141  };
142 
143  exportToCSVMenuItem.addActionListener(actList);
144  selectAllMenuItem.addActionListener(actList);
145  showCaseDetailsMenuItem.addActionListener(actList);
146  showCommonalityMenuItem.addActionListener(actList);
147 
148  // Set background of every nth row as light grey.
149  TableCellRenderer renderer = new OtherOccurrencesFilesTableCellRenderer();
150  filesTable.setDefaultRenderer(Object.class, renderer);
151 
152  // Configure column sorting.
153  TableRowSorter<TableModel> sorter = new TableRowSorter<>(filesTable.getModel());
154  filesTable.setRowSorter(sorter);
155  casesTable.getSelectionModel().addListSelectionListener((e) -> {
156  if (Case.isCaseOpen()) {
157  updateOnCaseSelection();
158  }
159  });
160  dataSourcesTable.getSelectionModel().addListSelectionListener((e) -> {
161  if (Case.isCaseOpen()) {
162  updateOnDataSourceSelection();
163  }
164  });
165  casesTable.getRowSorter().toggleSortOrder(0);
166  dataSourcesTable.getRowSorter().toggleSortOrder(0);
167  }
168 
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."})
180  private void showCommonalityDetails() {
181  if (correlationAttributes.isEmpty()) {
182  JOptionPane.showConfirmDialog(showCommonalityMenuItem,
183  Bundle.DataContentViewerOtherCases_correlatedArtifacts_isEmpty(),
184  Bundle.DataContentViewerOtherCases_correlatedArtifacts_title(),
185  DEFAULT_OPTION, PLAIN_MESSAGE);
186  } else {
187  StringBuilder msg = new StringBuilder(correlationAttributes.size());
188  int percentage;
189  try {
190  EamDb dbManager = EamDb.getInstance();
191  for (CorrelationAttributeInstance eamArtifact : correlationAttributes) {
192  try {
193  percentage = dbManager.getFrequencyPercentage(eamArtifact);
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);
199  }
200  }
201  JOptionPane.showConfirmDialog(showCommonalityMenuItem,
202  msg.toString(),
203  Bundle.DataContentViewerOtherCases_correlatedArtifacts_title(),
204  DEFAULT_OPTION, PLAIN_MESSAGE);
205  } catch (EamDbException ex) {
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);
211  }
212  }
213  }
214 
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."})
220  private void showCaseDetails(int selectedRowViewIdx) {
221 
222  String caseDisplayName = Bundle.DataContentViewerOtherCases_caseDetailsDialog_noCaseNameError();
223  try {
224  if (-1 != selectedRowViewIdx) {
225  EamDb dbManager = EamDb.getInstance();
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(),
232  caseDisplayName,
233  DEFAULT_OPTION, PLAIN_MESSAGE);
234  return;
235  }
236  caseDisplayName = eamCasePartial.getDisplayName();
237  // query case details
238  CorrelationCase eamCase = dbManager.getCaseByUUID(eamCasePartial.getCaseUUID());
239  if (eamCase == null) {
240  JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
241  Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetails(),
242  caseDisplayName,
243  DEFAULT_OPTION, PLAIN_MESSAGE);
244  return;
245  }
246 
247  // display case details
248  JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
250  caseDisplayName,
251  DEFAULT_OPTION, PLAIN_MESSAGE);
252  } else {
253  JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
254  Bundle.DataContentViewerOtherCases_caseDetailsDialog_notSelected(),
255  caseDisplayName,
256  DEFAULT_OPTION, PLAIN_MESSAGE);
257  }
258  } catch (EamDbException ex) {
259  LOGGER.log(Level.SEVERE, "Error loading case details", ex);
260  JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
261  Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetails(),
262  caseDisplayName,
263  DEFAULT_OPTION, PLAIN_MESSAGE);
264  }
265  }
266 
267  private void saveToCSV() throws NoCurrentCaseException {
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);
271  CSVFileChooser.setCurrentDirectory(new File(Case.getCurrentCaseThrows().getExportDirectory()));
272  CSVFileChooser.setSelectedFile(new File(fileName));
273  CSVFileChooser.setFileFilter(new FileNameExtensionFilter("csv file", "csv"));
274 
275  int returnVal = CSVFileChooser.showSaveDialog(filesTable);
276  if (returnVal == JFileChooser.APPROVE_OPTION) {
277 
278  File selectedFile = CSVFileChooser.getSelectedFile();
279  if (!selectedFile.getName().endsWith(".csv")) { // NON-NLS
280  selectedFile = new File(selectedFile.toString() + ".csv"); // NON-NLS
281  }
282 
283  writeSelectedRowsToFileAsCSV(selectedFile);
284  }
285  }
286  }
287 
288  private void writeSelectedRowsToFileAsCSV(File destFile) {
289  StringBuilder content;
290  int[] selectedRowViewIndices = filesTable.getSelectedRows();
291  int colCount = tableModel.getColumnCount();
292 
293  try (BufferedWriter writer = Files.newBufferedWriter(destFile.toPath())) {
294 
295  // write column names
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)) {
300  content.append(",");
301  }
302  }
303 
304  content.append(System.getProperty("line.separator"));
305  writer.write(content.toString());
306 
307  // write rows
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)) {
314  content.append(",");
315  }
316  }
317  content.append(System.getProperty("line.separator"));
318  writer.write(content.toString());
319  }
320 
321  } catch (IOException ex) {
322  LOGGER.log(Level.SEVERE, "Error writing selected rows to CSV.", ex);
323  }
324  }
325 
329  private void reset() {
330  // start with empty table
331  casesTableModel.clearTable();
332  ((DefaultTableModel) dataSourcesTable.getModel()).setRowCount(0);
333  tableModel.clearTable();
334  correlationAttributes.clear();
335  earliestCaseDate.setText(Bundle.DataContentViewerOtherCases_earliestCaseNotAvailable());
336  foundInLabel.setText("");
337  }
338 
339  @Override
340  public String getTitle() {
341  return Bundle.DataContentViewerOtherCases_title();
342  }
343 
344  @Override
345  public String getToolTip() {
346  return Bundle.DataContentViewerOtherCases_toolTip();
347  }
348 
349  @Override
351  return new DataContentViewerOtherCases();
352  }
353 
354  @Override
355  public Component getComponent() {
356  return this;
357  }
358 
359  @Override
360  public void resetComponent() {
361  reset();
362  }
363 
364  @Override
365  public int isPreferred(Node node) {
366  return 1;
367  }
368 
376  private BlackboardArtifact
378  BlackboardArtifactTag nodeBbArtifactTag = node.getLookup().lookup(BlackboardArtifactTag.class
379  );
380  BlackboardArtifact nodeBbArtifact = node.getLookup().lookup(BlackboardArtifact.class
381  );
382 
383  if (nodeBbArtifactTag != null) {
384  return nodeBbArtifactTag.getArtifact();
385  } else if (nodeBbArtifact != null) {
386  return nodeBbArtifact;
387  }
388 
389  return null;
390 
391  }
392 
400  private AbstractFile getAbstractFileFromNode(Node node) {
401  BlackboardArtifactTag nodeBbArtifactTag = node.getLookup().lookup(BlackboardArtifactTag.class
402  );
403  ContentTag nodeContentTag = node.getLookup().lookup(ContentTag.class
404  );
405  BlackboardArtifact nodeBbArtifact = node.getLookup().lookup(BlackboardArtifact.class
406  );
407  AbstractFile nodeAbstractFile = node.getLookup().lookup(AbstractFile.class
408  );
409 
410  if (nodeBbArtifactTag != null) {
411  Content content = nodeBbArtifactTag.getContent();
412  if (content instanceof AbstractFile) {
413  return (AbstractFile) content;
414  }
415  } else if (nodeContentTag != null) {
416  Content content = nodeContentTag.getContent();
417  if (content instanceof AbstractFile) {
418  return (AbstractFile) content;
419  }
420  } else if (nodeBbArtifact != null) {
421  Content content;
422  try {
423  content = nodeBbArtifact.getSleuthkitCase().getContentById(nodeBbArtifact.getObjectID());
424  } catch (TskCoreException ex) {
425  LOGGER.log(Level.SEVERE, "Error retrieving blackboard artifact", ex); // NON-NLS
426  return null;
427  }
428 
429  if (content instanceof AbstractFile) {
430  return (AbstractFile) content;
431  }
432  } else if (nodeAbstractFile != null) {
433  return nodeAbstractFile;
434  }
435 
436  return null;
437  }
438 
447  private Collection<CorrelationAttributeInstance> getCorrelationAttributesFromNode(Node node) {
448  Collection<CorrelationAttributeInstance> ret = new ArrayList<>();
449 
450  // correlate on blackboard artifact attributes if they exist and supported
451  BlackboardArtifact bbArtifact = getBlackboardArtifactFromNode(node);
452  if (bbArtifact != null && EamDb.isEnabled()) {
453  ret.addAll(EamArtifactUtil.makeInstancesFromBlackboardArtifact(bbArtifact, false));
454  }
455 
456  // we can correlate based on the MD5 if it is enabled
457  if (this.file != null && EamDb.isEnabled() && this.file.getSize() > 0) {
458  try {
459 
461  String md5 = this.file.getMd5Hash();
462  if (md5 != null && !md5.isEmpty() && null != artifactTypes && !artifactTypes.isEmpty()) {
463  for (CorrelationAttributeInstance.Type aType : artifactTypes) {
464  if (aType.getId() == CorrelationAttributeInstance.FILES_TYPE_ID) {
466  try {
467  ret.add(new CorrelationAttributeInstance(
468  aType,
469  md5,
470  corCase,
471  CorrelationDataSource.fromTSKDataSource(corCase, file.getDataSource()),
472  file.getParentPath() + file.getName(),
473  "",
474  file.getKnown(),
475  file.getId()));
477  LOGGER.log(Level.INFO, String.format("Unable to check create CorrelationAttribtueInstance for value %s and type %s.", md5, aType.toString()), ex);
478  }
479  break;
480  }
481  }
482  }
483  } catch (EamDbException | TskCoreException ex) {
484  LOGGER.log(Level.SEVERE, "Error connecting to DB", ex); // NON-NLS
485  }
486  // If EamDb not enabled, get the Files default correlation type to allow Other Occurances to be enabled.
487  } else if (this.file != null && this.file.getSize() > 0) {
488  String md5 = this.file.getMd5Hash();
489  if (md5 != null && !md5.isEmpty()) {
490  try {
491  final CorrelationAttributeInstance.Type fileAttributeType
493  .stream()
494  .filter(attrType -> attrType.getId() == CorrelationAttributeInstance.FILES_TYPE_ID)
495  .findAny()
496  .get();
497  //The Central Repository is not enabled
498  ret.add(new CorrelationAttributeInstance(fileAttributeType, md5, null, null, "", "", TskData.FileKnown.UNKNOWN, this.file.getId()));
499  } catch (EamDbException ex) {
500  LOGGER.log(Level.SEVERE, "Error connecting to DB", ex); // NON-NLS
502  LOGGER.log(Level.INFO, String.format("Unable to create CorrelationAttributeInstance for value %s", md5), ex); // NON-NLS
503  }
504  }
505  }
506 
507  return ret;
508  }
509 
510  @Messages({"DataContentViewerOtherCases.earliestCaseNotAvailable= Not Enabled."})
515  private void setEarliestCaseDate() {
516  String dateStringDisplay = Bundle.DataContentViewerOtherCases_earliestCaseNotAvailable();
517 
518  if (EamDb.isEnabled()) {
519  LocalDateTime earliestDate = LocalDateTime.now(DateTimeZone.UTC);
520  DateFormat datetimeFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss", Locale.US);
521  try {
522  EamDb dbManager = EamDb.getInstance();
523  List<CorrelationCase> cases = dbManager.getCases();
524  for (CorrelationCase aCase : cases) {
525  LocalDateTime caseDate = LocalDateTime.fromDateFields(datetimeFormat.parse(aCase.getCreationDate()));
526 
527  if (caseDate.isBefore(earliestDate)) {
528  earliestDate = caseDate;
529  dateStringDisplay = aCase.getCreationDate();
530  }
531 
532  }
533 
534  } catch (EamDbException ex) {
535  LOGGER.log(Level.SEVERE, "Error getting list of cases from database.", ex); // NON-NLS
536  } catch (ParseException ex) {
537  LOGGER.log(Level.SEVERE, "Error parsing date of cases from database.", ex); // NON-NLS
538  }
539 
540  }
541  earliestCaseDate.setText(dateStringDisplay);
542  }
543 
556  private Map<UniquePathKey, OtherOccurrenceNodeInstanceData> getCorrelatedInstances(CorrelationAttributeInstance corAttr, String dataSourceName, String deviceId) {
557  // @@@ Check exception
558  try {
559  final Case openCase = Case.getCurrentCaseThrows();
560  String caseUUID = openCase.getName();
561 
562  HashMap<UniquePathKey, OtherOccurrenceNodeInstanceData> nodeDataMap = new HashMap<>();
563 
564  if (EamDb.isEnabled()) {
565  List<CorrelationAttributeInstance> instances = EamDb.getInstance().getArtifactInstancesByTypeValue(corAttr.getCorrelationType(), corAttr.getCorrelationValue());
566 
567  for (CorrelationAttributeInstance artifactInstance : instances) {
568 
569  // Only add the attribute if it isn't the object the user selected.
570  // We consider it to be a different object if at least one of the following is true:
571  // - the case UUID is different
572  // - the data source name is different
573  // - the data source device ID is different
574  // - the file path is different
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())) {
579 
580  OtherOccurrenceNodeInstanceData newNode = new OtherOccurrenceNodeInstanceData(artifactInstance, corAttr.getCorrelationType(), corAttr.getCorrelationValue());
581  UniquePathKey uniquePathKey = new UniquePathKey(newNode);
582  nodeDataMap.put(uniquePathKey, newNode);
583  }
584  }
585  }
586 
587  if (corAttr.getCorrelationType().getDisplayName().equals("Files")) {
588  List<AbstractFile> caseDbFiles = getCaseDbMatches(corAttr, openCase);
589 
590  for (AbstractFile caseDbFile : caseDbFiles) {
591  addOrUpdateNodeData(openCase, nodeDataMap, caseDbFile);
592  }
593  }
594 
595  return nodeDataMap;
596  } catch (EamDbException ex) {
597  LOGGER.log(Level.SEVERE, "Error getting artifact instances from database.", ex); // NON-NLS
599  LOGGER.log(Level.INFO, "Error getting artifact instances from database.", ex); // NON-NLS
600  } catch (NoCurrentCaseException ex) {
601  LOGGER.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS
602  } catch (TskCoreException ex) {
603  // do nothing.
604  // @@@ Review this behavior
605  LOGGER.log(Level.SEVERE, "Exception while querying open case.", ex); // NON-NLS
606  }
607 
608  return new HashMap<>(0);
609  }
610 
624  private List<AbstractFile> getCaseDbMatches(CorrelationAttributeInstance corAttr, Case openCase) throws NoCurrentCaseException, TskCoreException, EamDbException {
625  String md5 = corAttr.getCorrelationValue();
626  SleuthkitCase tsk = openCase.getSleuthkitCase();
627  List<AbstractFile> matches = tsk.findAllFilesWhere(String.format("md5 = '%s'", new Object[]{md5}));
628 
629  List<AbstractFile> caseDbArtifactInstances = new ArrayList<>();
630  for (AbstractFile fileMatch : matches) {
631  if (this.file.equals(fileMatch)) {
632  continue; // If this is the file the user clicked on
633  }
634  caseDbArtifactInstances.add(fileMatch);
635  }
636  return caseDbArtifactInstances;
637 
638  }
639 
650  private void addOrUpdateNodeData(final Case autopsyCase, Map<UniquePathKey, OtherOccurrenceNodeInstanceData> nodeDataMap, AbstractFile newFile) throws TskCoreException, EamDbException {
651 
652  OtherOccurrenceNodeInstanceData newNode = new OtherOccurrenceNodeInstanceData(newFile, autopsyCase);
653 
654  // If the caseDB object has a notable tag associated with it, update
655  // the known status to BAD
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);
662  break;
663  }
664  }
665  }
666 
667  // Make a key to see if the file is already in the map
668  UniquePathKey uniquePathKey = new UniquePathKey(newNode);
669 
670  // If this node is already in the list, the only thing we need to do is
671  // update the known status to BAD if the caseDB version had known status BAD.
672  // Otherwise this is a new node so add the new node to the map.
673  if (nodeDataMap.containsKey(uniquePathKey)) {
674  if (newNode.getKnown() == TskData.FileKnown.BAD) {
675  OtherOccurrenceNodeInstanceData prevInstance = nodeDataMap.get(uniquePathKey);
676  prevInstance.updateKnown(newNode.getKnown());
677  }
678  } else {
679  nodeDataMap.put(uniquePathKey, newNode);
680  }
681  }
682 
683  @Override
684  public boolean isSupported(Node node) {
685 
686  // Is supported if one of the following is true:
687  // - The central repo is enabled and the node has correlatable content
688  // (either through the MD5 hash of the associated file or through a BlackboardArtifact)
689  // - The central repo is disabled and the backing file has a valid MD5 hash
690  this.file = this.getAbstractFileFromNode(node);
691  if (EamDb.isEnabled()) {
692  return !getCorrelationAttributesFromNode(node).isEmpty();
693  } else {
694  return this.file != null
695  && this.file.getSize() > 0
696  && ((this.file.getMd5Hash() != null) && (!this.file.getMd5Hash().isEmpty()));
697  }
698  }
699 
700  @Override
701  public void setNode(Node node) {
702 
703  reset(); // reset the table to empty.
704  if (node == null) {
705  return;
706  }
707  //could be null
708  this.file = this.getAbstractFileFromNode(node);
709  populateTable(node);
710 
711  }
712 
719  @Messages({
720  "DataContentViewerOtherCases.dataSources.header.text=Data Source Name",
721  "DataContentViewerOtherCases.foundIn.text=Found %d instances in %d cases and %d data sources."
722  })
723  private void populateTable(Node node) {
724  try {
725  if (this.file != null) {
726  Content dataSource = this.file.getDataSource();
727  dataSourceName = dataSource.getName();
728  deviceId = Case.getCurrentCaseThrows().getSleuthkitCase().getDataSource(dataSource.getId()).getDeviceId();
729  }
730  } catch (TskException | NoCurrentCaseException ex) {
731  // do nothing.
732  // @@@ Review this behavior
733  }
734 
735  // get the attributes we can correlate on
736  correlationAttributes.addAll(getCorrelationAttributesFromNode(node));
737  Map<String, CorrelationCase> caseNames = new HashMap<>();
738  int totalCount = 0;
739  Set<String> dataSources = new HashSet<>();
740  for (CorrelationAttributeInstance corAttr : correlationAttributes) {
741  Map<UniquePathKey, OtherOccurrenceNodeInstanceData> correlatedNodeDataMap = new HashMap<>(0);
742 
743  // get correlation and reference set instances from DB
744  correlatedNodeDataMap.putAll(getCorrelatedInstances(corAttr, dataSourceName, deviceId));
745  for (OtherOccurrenceNodeInstanceData nodeData : correlatedNodeDataMap.values()) {
746  if (nodeData.isCentralRepoNode()) {
747  try {
748  dataSources.add(makeDataSourceString(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID(), nodeData.getDeviceID(), nodeData.getDataSourceName()));
749  caseNames.put(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID(), nodeData.getCorrelationAttributeInstance().getCorrelationCase());
750  } catch (EamDbException ex) {
751  LOGGER.log(Level.WARNING, "Unable to get correlation case for displaying other occurrence for case: " + nodeData.getCaseName());
752  }
753  } else {
754  try {
755  dataSources.add(makeDataSourceString(Case.getCurrentCaseThrows().getName(), nodeData.getDeviceID(), nodeData.getDataSourceName()));
757  } catch (NoCurrentCaseException ex) {
758  LOGGER.log(Level.WARNING, "No current case open for other occurrences");
759  }
760  }
761  totalCount++;
762  }
763  }
764  for (CorrelationCase corCase : caseNames.values()) {
765  casesTableModel.addCorrelationCase(new CorrelationCaseWrapper(corCase));
766  }
767  int caseCount = casesTableModel.getRowCount();
768  if (correlationAttributes.isEmpty()) {
769  casesTableModel.addCorrelationCase(NO_ARTIFACTS_CASE);
770  } else if (caseCount == 0) {
771  casesTableModel.addCorrelationCase(NO_RESULTS_CASE);
772  }
773  setColumnWidths();
774  setEarliestCaseDate();
775  foundInLabel.setText(String.format(Bundle.DataContentViewerOtherCases_foundIn_text(), totalCount, caseCount, dataSources.size()));
776  if (caseCount > 0) {
777  casesTable.setRowSelectionInterval(0, 0);
778  }
779  }
780 
785  private String makeDataSourceString(String caseUUID, String deviceId, String dataSourceName) {
786  return caseUUID + deviceId + dataSourceName;
787  }
788 
792  private void updateOnCaseSelection() {
793  int[] selectedCaseIndexes = casesTable.getSelectedRows();
794  DefaultTableModel dataSourceModel = (DefaultTableModel) dataSourcesTable.getModel();
795  dataSourceModel.setRowCount(0);
796  tableModel.clearTable();
797  for (CorrelationAttributeInstance corAttr : correlationAttributes) {
798  Map<UniquePathKey, OtherOccurrenceNodeInstanceData> correlatedNodeDataMap = new HashMap<>(0);
799 
800  // get correlation and reference set instances from DB
801  correlatedNodeDataMap.putAll(getCorrelatedInstances(corAttr, dataSourceName, deviceId));
802  for (OtherOccurrenceNodeInstanceData nodeData : correlatedNodeDataMap.values()) {
803  for (int selectedRow : selectedCaseIndexes) {
804  try {
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()});
809  }
810  } else {
811  dataSourceModel.addRow(new Object[]{nodeData.getDataSourceName(), nodeData.getDeviceID()});
812  }
813  } catch (EamDbException ex) {
814  LOGGER.log(Level.WARNING, "Unable to get correlation attribute instance from OtherOccurrenceNodeInstanceData for case " + nodeData.getCaseName());
815  }
816  }
817  }
818  }
819  if (dataSourcesTable.getRowCount() > 0) {
820  dataSourcesTable.setRowSelectionInterval(0, 0);
821  }
822  }
823 
829  int[] selectedCaseIndexes = casesTable.getSelectedRows();
830  DefaultTableModel dataSourceModel = (DefaultTableModel) dataSourcesTable.getModel();
831  int[] selectedDataSources = dataSourcesTable.getSelectedRows();
832  tableModel.clearTable();
833  for (CorrelationAttributeInstance corAttr : correlationAttributes) {
834  Map<UniquePathKey, OtherOccurrenceNodeInstanceData> correlatedNodeDataMap = new HashMap<>(0);
835 
836  // get correlation and reference set instances from DB
837  correlatedNodeDataMap.putAll(getCorrelatedInstances(corAttr, dataSourceName, deviceId));
838  for (OtherOccurrenceNodeInstanceData nodeData : correlatedNodeDataMap.values()) {
839  for (int selectedCaseRow : selectedCaseIndexes) {
840  for (int selectedDataSourceRow : selectedDataSources) {
841  try {
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);
847  }
848  } else {
849  if (dataSourceModel.getValueAt(dataSourcesTable.convertRowIndexToModel(selectedDataSourceRow), 1).toString().equals(nodeData.getDeviceID())) {
850  tableModel.addNodeData(nodeData);
851  }
852  }
853  } catch (EamDbException ex) {
854  LOGGER.log(Level.WARNING, "Unable to get correlation attribute instance from OtherOccurrenceNodeInstanceData for case " + nodeData.getCaseName());
855  }
856  }
857  }
858  }
859  }
860  }
861 
865  private void setColumnWidths() {
866  for (int idx = 0; idx < tableModel.getColumnCount(); idx++) {
867  TableColumn column = filesTable.getColumnModel().getColumn(idx);
868  column.setMinWidth(DEFAULT_MIN_CELL_WIDTH);
869  int columnWidth = tableModel.getColumnPreferredWidth(idx);
870  if (columnWidth > 0) {
871  column.setPreferredWidth(columnWidth);
872  }
873  }
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);
877  } else {
878  dataSourcesTable.getColumnModel().getColumn(idx).setPreferredWidth(210);
879  }
880  }
881  }
882 
888  @SuppressWarnings("unchecked")
889  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
890  private void initComponents() {
891 
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();
911 
912  rightClickPopupMenu.addPopupMenuListener(new javax.swing.event.PopupMenuListener() {
913  public void popupMenuCanceled(javax.swing.event.PopupMenuEvent evt) {
914  }
915  public void popupMenuWillBecomeInvisible(javax.swing.event.PopupMenuEvent evt) {
916  }
917  public void popupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt) {
918  rightClickPopupMenuPopupMenuWillBecomeVisible(evt);
919  }
920  });
921 
922  org.openide.awt.Mnemonics.setLocalizedText(selectAllMenuItem, org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.selectAllMenuItem.text")); // NOI18N
923  rightClickPopupMenu.add(selectAllMenuItem);
924 
925  org.openide.awt.Mnemonics.setLocalizedText(exportToCSVMenuItem, org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.exportToCSVMenuItem.text")); // NOI18N
926  rightClickPopupMenu.add(exportToCSVMenuItem);
927 
928  org.openide.awt.Mnemonics.setLocalizedText(showCaseDetailsMenuItem, org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.showCaseDetailsMenuItem.text")); // NOI18N
929  rightClickPopupMenu.add(showCaseDetailsMenuItem);
930 
931  org.openide.awt.Mnemonics.setLocalizedText(showCommonalityMenuItem, org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.showCommonalityMenuItem.text")); // NOI18N
932  rightClickPopupMenu.add(showCommonalityMenuItem);
933 
934  setMinimumSize(new java.awt.Dimension(1500, 10));
935  setOpaque(false);
936  setPreferredSize(new java.awt.Dimension(1500, 44));
937 
938  otherCasesPanel.setPreferredSize(new java.awt.Dimension(921, 62));
939 
940  tableContainerPanel.setPreferredSize(new java.awt.Dimension(1500, 63));
941 
942  org.openide.awt.Mnemonics.setLocalizedText(earliestCaseLabel, org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.earliestCaseLabel.text")); // NOI18N
943  earliestCaseLabel.setToolTipText(org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.earliestCaseLabel.toolTipText")); // NOI18N
944 
945  org.openide.awt.Mnemonics.setLocalizedText(earliestCaseDate, org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.earliestCaseDate.text")); // NOI18N
946 
947  org.openide.awt.Mnemonics.setLocalizedText(foundInLabel, org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.foundInLabel.text")); // NOI18N
948 
949  jSplitPane2.setDividerLocation(470);
950 
951  jSplitPane3.setDividerLocation(150);
952 
953  casesTable.setAutoCreateRowSorter(true);
954  casesTable.setModel(casesTableModel);
955  caseScrollPane.setViewportView(casesTable);
956 
957  jSplitPane3.setLeftComponent(caseScrollPane);
958 
959  dataSourcesTable.setAutoCreateRowSorter(true);
960  dataSourcesTable.setModel(new javax.swing.table.DefaultTableModel(
961  new Object [][] {
962 
963  },
964  new String [] {
965  "Data Source Name", "Device ID"
966  }
967  ) {
968  boolean[] canEdit = new boolean [] {
969  false, false
970  };
971 
972  public boolean isCellEditable(int rowIndex, int columnIndex) {
973  return canEdit [columnIndex];
974  }
975  });
976  dataSourceScrollPane.setViewportView(dataSourcesTable);
977 
978  jSplitPane3.setRightComponent(dataSourceScrollPane);
979 
980  jSplitPane2.setLeftComponent(jSplitPane3);
981 
982  propertiesTableScrollPane.setPreferredSize(new java.awt.Dimension(1000, 30));
983 
984  filesTable.setAutoCreateRowSorter(true);
985  filesTable.setModel(tableModel);
986  filesTable.setToolTipText(org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.table.toolTip.text")); // NOI18N
987  filesTable.setComponentPopupMenu(rightClickPopupMenu);
988  filesTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_INTERVAL_SELECTION);
989  propertiesTableScrollPane.setViewportView(filesTable);
990 
991  jSplitPane2.setRightComponent(propertiesTableScrollPane);
992 
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)
1003  .addGap(66, 66, 66)
1004  .addComponent(foundInLabel))
1005  .addComponent(jSplitPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 911, Short.MAX_VALUE))
1006  .addContainerGap())
1007  );
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))
1017  .addContainerGap())
1018  );
1019 
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)
1028  .addGap(0, 0, 0)))
1029  );
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)
1036  .addGap(0, 0, 0)))
1037  );
1038 
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)
1044  );
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)
1048  );
1049  }// </editor-fold>//GEN-END:initComponents
1050 
1051  private void rightClickPopupMenuPopupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt) {//GEN-FIRST:event_rightClickPopupMenuPopupMenuWillBecomeVisible
1052  boolean enableCentralRepoActions = false;
1053 
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();
1060  }
1061  }
1062  showCaseDetailsMenuItem.setVisible(enableCentralRepoActions);
1063  showCommonalityMenuItem.setVisible(enableCentralRepoActions);
1064  }//GEN-LAST:event_rightClickPopupMenuPopupMenuWillBecomeVisible
1065 
1066  // Variables declaration - do not modify//GEN-BEGIN:variables
1067  private javax.swing.JFileChooser CSVFileChooser;
1068  private javax.swing.JScrollPane caseScrollPane;
1069  private javax.swing.JTable casesTable;
1070  private javax.swing.JScrollPane dataSourceScrollPane;
1071  private javax.swing.JTable dataSourcesTable;
1072  private javax.swing.JLabel earliestCaseDate;
1073  private javax.swing.JLabel earliestCaseLabel;
1074  private javax.swing.JMenuItem exportToCSVMenuItem;
1075  private javax.swing.JTable filesTable;
1076  private javax.swing.JLabel foundInLabel;
1077  private javax.swing.JSplitPane jSplitPane2;
1078  private javax.swing.JSplitPane jSplitPane3;
1079  private javax.swing.JPanel otherCasesPanel;
1080  private javax.swing.JScrollPane propertiesTableScrollPane;
1081  private javax.swing.JPopupMenu rightClickPopupMenu;
1082  private javax.swing.JMenuItem selectAllMenuItem;
1083  private javax.swing.JMenuItem showCaseDetailsMenuItem;
1084  private javax.swing.JMenuItem showCommonalityMenuItem;
1085  private javax.swing.JPanel tableContainerPanel;
1086  // End of variables declaration//GEN-END:variables
1087 
1092  private static final class UniquePathKey {
1093 
1094  private final String dataSourceID;
1095  private final String filePath;
1096  private final String type;
1097 
1098  UniquePathKey(OtherOccurrenceNodeInstanceData nodeData) {
1099  super();
1100  dataSourceID = nodeData.getDeviceID();
1101  if (nodeData.getFilePath() != null) {
1102  filePath = nodeData.getFilePath().toLowerCase();
1103  } else {
1104  filePath = null;
1105  }
1106  type = nodeData.getType();
1107  }
1108 
1109  @Override
1110  public boolean equals(Object other) {
1111  if (other instanceof UniquePathKey) {
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()));
1116  }
1117  return false;
1118  }
1119 
1120  @Override
1121  public int hashCode() {
1122  //int hash = 7;
1123  //hash = 67 * hash + this.dataSourceID.hashCode();
1124  //hash = 67 * hash + this.filePath.hashCode();
1125  return Objects.hash(getDataSourceID(), getFilePath(), getType());
1126  }
1127 
1133  String getType() {
1134  return type;
1135  }
1136 
1142  String getFilePath() {
1143  return filePath;
1144  }
1145 
1151  String getDataSourceID() {
1152  return dataSourceID;
1153  }
1154  }
1155 }
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 Mar 22 2019
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.