Autopsy  4.7.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-2018 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.util.ArrayList;
29 import java.util.Calendar;
30 import java.util.Collection;
31 import java.util.HashMap;
32 import java.util.List;
33 import java.util.Map;
34 import java.util.Objects;
35 import java.util.logging.Level;
37 import java.util.stream.Collectors;
38 import javax.swing.JFileChooser;
39 import javax.swing.JMenuItem;
40 import javax.swing.JOptionPane;
41 import static javax.swing.JOptionPane.DEFAULT_OPTION;
42 import static javax.swing.JOptionPane.PLAIN_MESSAGE;
43 import static javax.swing.JOptionPane.ERROR_MESSAGE;
44 import javax.swing.JPanel;
45 import javax.swing.filechooser.FileNameExtensionFilter;
46 import javax.swing.table.TableCellRenderer;
47 import javax.swing.table.TableColumn;
48 import org.openide.nodes.Node;
49 import org.openide.util.NbBundle.Messages;
50 import org.openide.util.lookup.ServiceProvider;
61 import org.sleuthkit.datamodel.AbstractFile;
62 import org.sleuthkit.datamodel.BlackboardArtifact;
63 import org.sleuthkit.datamodel.BlackboardArtifactTag;
64 import org.sleuthkit.datamodel.Content;
65 import org.sleuthkit.datamodel.ContentTag;
66 import org.sleuthkit.datamodel.TskCoreException;
67 import org.sleuthkit.datamodel.TskException;
70 import org.sleuthkit.datamodel.SleuthkitCase;
71 import org.sleuthkit.datamodel.TskData;
72 import org.sleuthkit.datamodel.TskDataException;
73 
77 @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
78 @ServiceProvider(service = DataContentViewer.class, position = 8)
79 @Messages({"DataContentViewerOtherCases.title=Other Occurrences",
80  "DataContentViewerOtherCases.toolTip=Displays instances of the selected file/artifact from other occurrences.",})
81 public class DataContentViewerOtherCases extends JPanel implements DataContentViewer {
82 
83  private final static Logger logger = Logger.getLogger(DataContentViewerOtherCases.class.getName());
84 
86  private final Collection<CorrelationAttribute> correlationAttributes;
90  private AbstractFile file;
91 
96  this.tableModel = new DataContentViewerOtherCasesTableModel();
97  this.correlationAttributes = new ArrayList<>();
98 
99  initComponents();
100  customizeComponents();
101  reset();
102  }
103 
104  private void customizeComponents() {
105  ActionListener actList = new ActionListener() {
106  @Override
107  public void actionPerformed(ActionEvent e) {
108  JMenuItem jmi = (JMenuItem) e.getSource();
109  if (jmi.equals(selectAllMenuItem)) {
110  otherCasesTable.selectAll();
111  } else if (jmi.equals(showCaseDetailsMenuItem)) {
112  showCaseDetails(otherCasesTable.getSelectedRow());
113  } else if (jmi.equals(exportToCSVMenuItem)) {
114  try {
115  saveToCSV();
116  } catch (NoCurrentCaseException ex) {
117  logger.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS
118  }
119  } else if (jmi.equals(showCommonalityMenuItem)) {
120  showCommonalityDetails();
121  } else if (jmi.equals(addCommentMenuItem)) {
122  CorrelationAttribute selectedAttribute = (CorrelationAttribute) tableModel.getRow(otherCasesTable.getSelectedRow());
124  action.addEditCentralRepoComment();
125  otherCasesTable.repaint();
126  }
127  }
128  };
129 
130  exportToCSVMenuItem.addActionListener(actList);
131  selectAllMenuItem.addActionListener(actList);
132  showCaseDetailsMenuItem.addActionListener(actList);
133  showCommonalityMenuItem.addActionListener(actList);
134  addCommentMenuItem.addActionListener(actList);
135 
136  // Set background of every nth row as light grey.
137  TableCellRenderer renderer = new DataContentViewerOtherCasesTableCellRenderer();
138  otherCasesTable.setDefaultRenderer(Object.class, renderer);
139  tableStatusPanelLabel.setVisible(false);
140  }
141 
142  @Messages({"DataContentViewerOtherCases.correlatedArtifacts.isEmpty=There are no files or artifacts to correlate.",
143  "# {0} - commonality percentage",
144  "# {1} - correlation type",
145  "# {2} - correlation value",
146  "DataContentViewerOtherCases.correlatedArtifacts.byType={0}% of data sources have {2} (type: {1})\n",
147  "DataContentViewerOtherCases.correlatedArtifacts.title=Attribute Frequency",
148  "DataContentViewerOtherCases.correlatedArtifacts.failed=Failed to get frequency details."})
153  private void showCommonalityDetails() {
154  if (correlationAttributes.isEmpty()) {
155  JOptionPane.showConfirmDialog(showCommonalityMenuItem,
156  Bundle.DataContentViewerOtherCases_correlatedArtifacts_isEmpty(),
157  Bundle.DataContentViewerOtherCases_correlatedArtifacts_title(),
158  DEFAULT_OPTION, PLAIN_MESSAGE);
159  } else {
160  StringBuilder msg = new StringBuilder();
161  int percentage;
162  try {
163  EamDb dbManager = EamDb.getInstance();
164  for (CorrelationAttribute eamArtifact : correlationAttributes) {
165  percentage = dbManager.getFrequencyPercentage(eamArtifact);
166  msg.append(Bundle.DataContentViewerOtherCases_correlatedArtifacts_byType(percentage,
167  eamArtifact.getCorrelationType().getDisplayName(),
168  eamArtifact.getCorrelationValue()));
169  }
170  JOptionPane.showConfirmDialog(showCommonalityMenuItem,
171  msg.toString(),
172  Bundle.DataContentViewerOtherCases_correlatedArtifacts_title(),
173  DEFAULT_OPTION, PLAIN_MESSAGE);
174  } catch (EamDbException ex) {
175  logger.log(Level.SEVERE, "Error getting commonality details.", ex);
176  JOptionPane.showConfirmDialog(showCommonalityMenuItem,
177  Bundle.DataContentViewerOtherCases_correlatedArtifacts_failed(),
178  Bundle.DataContentViewerOtherCases_correlatedArtifacts_title(),
179  DEFAULT_OPTION, ERROR_MESSAGE);
180  }
181  }
182  }
183 
184  @Messages({"DataContentViewerOtherCases.caseDetailsDialog.notSelected=No Row Selected",
185  "DataContentViewerOtherCases.caseDetailsDialog.noDetails=No details for this case.",
186  "DataContentViewerOtherCases.caseDetailsDialog.noDetailsReference=No case details for Global reference properties.",
187  "DataContentViewerOtherCases.caseDetailsDialog.noCaseNameError=Error",
188  "DataContentViewerOtherCases.noOpenCase.errMsg=No open case available."})
189  private void showCaseDetails(int selectedRowViewIdx) {
190  Case openCase;
191  try {
192  openCase = Case.getCurrentCaseThrows();
193  } catch (NoCurrentCaseException ex) {
194  JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
195  Bundle.DataContentViewerOtherCases_noOpenCase_errMsg(),
196  Bundle.DataContentViewerOtherCases_noOpenCase_errMsg(),
197  DEFAULT_OPTION, PLAIN_MESSAGE);
198  return;
199  }
200  String caseDisplayName = Bundle.DataContentViewerOtherCases_caseDetailsDialog_noCaseNameError();
201  try {
202  if (-1 != selectedRowViewIdx) {
203  EamDb dbManager = EamDb.getInstance();
204  int selectedRowModelIdx = otherCasesTable.convertRowIndexToModel(selectedRowViewIdx);
205  CorrelationAttribute eamArtifact = (CorrelationAttribute) tableModel.getRow(selectedRowModelIdx);
206  CorrelationCase eamCasePartial = eamArtifact.getInstances().get(0).getCorrelationCase();
207  if (eamCasePartial == null) {
208  JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
209  Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetailsReference(),
210  caseDisplayName,
211  DEFAULT_OPTION, PLAIN_MESSAGE);
212  return;
213  }
214  caseDisplayName = eamCasePartial.getDisplayName();
215  // query case details
216  CorrelationCase eamCase = dbManager.getCase(openCase);
217  if (eamCase == null) {
218  JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
219  Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetails(),
220  caseDisplayName,
221  DEFAULT_OPTION, PLAIN_MESSAGE);
222  return;
223  }
224 
225  // display case details
226  JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
228  caseDisplayName,
229  DEFAULT_OPTION, PLAIN_MESSAGE);
230  } else {
231  JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
232  Bundle.DataContentViewerOtherCases_caseDetailsDialog_notSelected(),
233  caseDisplayName,
234  DEFAULT_OPTION, PLAIN_MESSAGE);
235  }
236  } catch (EamDbException ex) {
237  JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
238  Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetails(),
239  caseDisplayName,
240  DEFAULT_OPTION, PLAIN_MESSAGE);
241  }
242  }
243 
244  private void saveToCSV() throws NoCurrentCaseException {
245  if (0 != otherCasesTable.getSelectedRowCount()) {
246  Calendar now = Calendar.getInstance();
247  String fileName = String.format("%1$tY%1$tm%1$te%1$tI%1$tM%1$tS_other_data_sources.csv", now);
248  CSVFileChooser.setCurrentDirectory(new File(Case.getCurrentCaseThrows().getExportDirectory()));
249  CSVFileChooser.setSelectedFile(new File(fileName));
250  CSVFileChooser.setFileFilter(new FileNameExtensionFilter("csv file", "csv"));
251 
252  int returnVal = CSVFileChooser.showSaveDialog(otherCasesTable);
253  if (returnVal == JFileChooser.APPROVE_OPTION) {
254 
255  File selectedFile = CSVFileChooser.getSelectedFile();
256  if (!selectedFile.getName().endsWith(".csv")) { // NON-NLS
257  selectedFile = new File(selectedFile.toString() + ".csv"); // NON-NLS
258  }
259 
260  writeSelectedRowsToFileAsCSV(selectedFile);
261  }
262  }
263  }
264 
265  private void writeSelectedRowsToFileAsCSV(File destFile) {
266  StringBuilder content;
267  int[] selectedRowViewIndices = otherCasesTable.getSelectedRows();
268  int colCount = tableModel.getColumnCount();
269 
270  try (BufferedWriter writer = Files.newBufferedWriter(destFile.toPath())) {
271 
272  // write column names
273  content = new StringBuilder("");
274  for (int colIdx = 0; colIdx < colCount; colIdx++) {
275  content.append('"').append(tableModel.getColumnName(colIdx)).append('"');
276  if (colIdx < (colCount - 1)) {
277  content.append(",");
278  }
279  }
280 
281  content.append(System.getProperty("line.separator"));
282  writer.write(content.toString());
283 
284  // write rows
285  for (int rowViewIdx : selectedRowViewIndices) {
286  content = new StringBuilder("");
287  for (int colIdx = 0; colIdx < colCount; colIdx++) {
288  int rowModelIdx = otherCasesTable.convertRowIndexToModel(rowViewIdx);
289  content.append('"').append(tableModel.getValueAt(rowModelIdx, colIdx)).append('"');
290  if (colIdx < (colCount - 1)) {
291  content.append(",");
292  }
293  }
294  content.append(System.getProperty("line.separator"));
295  writer.write(content.toString());
296  }
297 
298  } catch (IOException ex) {
299  logger.log(Level.SEVERE, "Error writing selected rows to CSV.", ex);
300  }
301  }
302 
306  private void reset() {
307  // start with empty table
308  tableModel.clearTable();
309  correlationAttributes.clear();
310  }
311 
312  @Override
313  public String getTitle() {
314  return Bundle.DataContentViewerOtherCases_title();
315  }
316 
317  @Override
318  public String getToolTip() {
319  return Bundle.DataContentViewerOtherCases_toolTip();
320  }
321 
322  @Override
324  return new DataContentViewerOtherCases();
325  }
326 
327  @Override
328  public Component getComponent() {
329  return this;
330  }
331 
332  @Override
333  public void resetComponent() {
334  reset();
335  }
336 
337  @Override
338  public int isPreferred(Node node) {
339  return 1;
340  }
341 
349  private BlackboardArtifact getBlackboardArtifactFromNode(Node node) {
350  BlackboardArtifactTag nodeBbArtifactTag = node.getLookup().lookup(BlackboardArtifactTag.class);
351  BlackboardArtifact nodeBbArtifact = node.getLookup().lookup(BlackboardArtifact.class);
352 
353  if (nodeBbArtifactTag != null) {
354  return nodeBbArtifactTag.getArtifact();
355  } else if (nodeBbArtifact != null) {
356  return nodeBbArtifact;
357  }
358 
359  return null;
360  }
361 
369  private AbstractFile getAbstractFileFromNode(Node node) {
370  BlackboardArtifactTag nodeBbArtifactTag = node.getLookup().lookup(BlackboardArtifactTag.class);
371  ContentTag nodeContentTag = node.getLookup().lookup(ContentTag.class);
372  BlackboardArtifact nodeBbArtifact = node.getLookup().lookup(BlackboardArtifact.class);
373  AbstractFile nodeAbstractFile = node.getLookup().lookup(AbstractFile.class);
374 
375  if (nodeBbArtifactTag != null) {
376  Content content = nodeBbArtifactTag.getContent();
377  if (content instanceof AbstractFile) {
378  return (AbstractFile) content;
379  }
380  } else if (nodeContentTag != null) {
381  Content content = nodeContentTag.getContent();
382  if (content instanceof AbstractFile) {
383  return (AbstractFile) content;
384  }
385  } else if (nodeBbArtifact != null) {
386  Content content;
387  try {
388  content = nodeBbArtifact.getSleuthkitCase().getContentById(nodeBbArtifact.getObjectID());
389  } catch (TskCoreException ex) {
390  logger.log(Level.SEVERE, "Error retrieving blackboard artifact", ex); // NON-NLS
391  return null;
392  }
393 
394  if (content instanceof AbstractFile) {
395  return (AbstractFile) content;
396  }
397  } else if (nodeAbstractFile != null) {
398  return nodeAbstractFile;
399  }
400 
401  return null;
402  }
403 
412  private Collection<CorrelationAttribute> getCorrelationAttributesFromNode(Node node) {
413  Collection<CorrelationAttribute> ret = new ArrayList<>();
414 
415  // correlate on blackboard artifact attributes if they exist and supported
416  BlackboardArtifact bbArtifact = getBlackboardArtifactFromNode(node);
417  if (bbArtifact != null && EamDb.isEnabled()) {
418  ret.addAll(EamArtifactUtil.getCorrelationAttributeFromBlackboardArtifact(bbArtifact, false, false));
419  }
420 
421  // we can correlate based on the MD5 if it is enabled
422  if (this.file != null && EamDb.isEnabled()) {
423  try {
424 
426  String md5 = this.file.getMd5Hash();
427  if (md5 != null && !md5.isEmpty() && null != artifactTypes && !artifactTypes.isEmpty()) {
428  for (CorrelationAttribute.Type aType : artifactTypes) {
429  if (aType.getId() == CorrelationAttribute.FILES_TYPE_ID) {
430  ret.add(new CorrelationAttribute(aType, md5));
431  break;
432  }
433  }
434  }
435  } catch (EamDbException ex) {
436  logger.log(Level.SEVERE, "Error connecting to DB", ex); // NON-NLS
437  }
438 
439  } else {
440  try {
441  // If EamDb not enabled, get the Files default correlation type to allow Other Occurances to be enabled.
442  if (this.file != null) {
443  String md5 = this.file.getMd5Hash();
444  if (md5 != null && !md5.isEmpty()) {
446  }
447  }
448  } catch (EamDbException ex) {
449  logger.log(Level.SEVERE, "Error connecting to DB", ex); // NON-NLS
450  }
451  }
452 
453  return ret;
454  }
455 
467  private Map<UniquePathKey, CorrelationAttributeInstance> getCorrelatedInstances(CorrelationAttribute corAttr, String dataSourceName, String deviceId) {
468  // @@@ Check exception
469  try {
470  final Case openCase = Case.getCurrentCase();
471  String caseUUID = openCase.getName();
472  String filePath = (file.getParentPath() + file.getName()).toLowerCase();
473  HashMap<UniquePathKey, CorrelationAttributeInstance> artifactInstances = new HashMap<>();
474 
475  if (EamDb.isEnabled()) {
476  EamDb dbManager = EamDb.getInstance();
477  artifactInstances.putAll(dbManager.getArtifactInstancesByTypeValue(corAttr.getCorrelationType(), corAttr.getCorrelationValue()).stream()
478  .filter(artifactInstance -> !artifactInstance.getFilePath().equals(filePath)
479  || !artifactInstance.getCorrelationCase().getCaseUUID().equals(caseUUID)
480  || !artifactInstance.getCorrelationDataSource().getName().equals(dataSourceName)
481  || !artifactInstance.getCorrelationDataSource().getDeviceID().equals(deviceId))
482  .collect(Collectors.toMap(correlationAttr -> new UniquePathKey(correlationAttr.getCorrelationDataSource().getDeviceID(), correlationAttr.getFilePath()),
483  correlationAttr -> correlationAttr)));
484  }
485 
486  if (corAttr.getCorrelationType().getDisplayName().equals("Files")) {
487  List<AbstractFile> caseDbFiles = addCaseDbMatches(corAttr, openCase);
488  for (AbstractFile caseDbFile : caseDbFiles) {
489  addOrUpdateAttributeInstance(openCase, artifactInstances, caseDbFile);
490  }
491  }
492 
493  return artifactInstances;
494  } catch (EamDbException ex) {
495  logger.log(Level.SEVERE, "Error getting artifact instances from database.", ex); // NON-NLS
496  } catch (NoCurrentCaseException ex) {
497  logger.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS
498  } catch (TskCoreException ex) {
499  // do nothing.
500  // @@@ Review this behavior
501  logger.log(Level.SEVERE, "Exception while querying open case.", ex); // NON-NLS
502  }
503 
504  return new HashMap<>(0);
505  }
506 
507  private List<AbstractFile> addCaseDbMatches(CorrelationAttribute corAttr, Case openCase) throws NoCurrentCaseException, TskCoreException, EamDbException {
508  String md5 = corAttr.getCorrelationValue();
509 
510  SleuthkitCase tsk = openCase.getSleuthkitCase();
511  List<AbstractFile> matches = tsk.findAllFilesWhere(String.format("md5 = '%s'", new Object[]{md5}));
512 
513  List<AbstractFile> caseDbArtifactInstances = new ArrayList<>();
514  for (AbstractFile fileMatch : matches) {
515  if (this.file.equals(fileMatch)) {
516  continue; // If this is the file the user clicked on
517  }
518  caseDbArtifactInstances.add(fileMatch);
519  }
520  return caseDbArtifactInstances;
521 
522  }
523 
534  private void addOrUpdateAttributeInstance(final Case autopsyCase, Map<UniquePathKey, CorrelationAttributeInstance> artifactInstances, AbstractFile newFile) throws TskCoreException, EamDbException {
535 
536  // figure out if the casedb file is known via either hash or tags
537  TskData.FileKnown localKnown = newFile.getKnown();
538 
539  if (localKnown != TskData.FileKnown.BAD) {
540  List<ContentTag> fileMatchTags = autopsyCase.getServices().getTagsManager().getContentTagsByContent(newFile);
541  for (ContentTag tag : fileMatchTags) {
542  TskData.FileKnown tagKnownStatus = tag.getName().getKnownStatus();
543  if (tagKnownStatus.equals(TskData.FileKnown.BAD)) {
544  localKnown = TskData.FileKnown.BAD;
545  break;
546  }
547  }
548  }
549 
550  // make a key to see if the file is already in the map
551  String filePath = newFile.getParentPath() + newFile.getName();
552  String deviceId;
553  try {
554  deviceId = autopsyCase.getSleuthkitCase().getDataSource(newFile.getDataSource().getId()).getDeviceId();
555  } catch (TskDataException | TskCoreException ex) {
556  logger.log(Level.WARNING, "Error getting data source info: {0}", ex);
557  return;
558  }
559  UniquePathKey uniquePathKey = new UniquePathKey(deviceId, filePath);
560 
561  // double check that the CR version is BAD if the caseDB version is BAD.
562  if (artifactInstances.containsKey(uniquePathKey)) {
563  if (localKnown == TskData.FileKnown.BAD) {
564  CorrelationAttributeInstance prevInstance = artifactInstances.get(uniquePathKey);
565  prevInstance.setKnownStatus(localKnown);
566  }
567  } // add the data from the case DB by pushing data into CorrelationAttributeInstance class
568  else {
569  // NOTE: If we are in here, it is likely because CR is not enabled. So, we cannot rely
570  // on any of the methods that query the DB.
571  CorrelationCase correlationCase = new CorrelationCase(autopsyCase.getName(), autopsyCase.getDisplayName());
572 
573  CorrelationDataSource correlationDataSource = CorrelationDataSource.fromTSKDataSource(correlationCase, newFile.getDataSource());
574 
575  CorrelationAttributeInstance caseDbInstance = new CorrelationAttributeInstance(correlationCase, correlationDataSource, filePath, "", localKnown);
576  artifactInstances.put(uniquePathKey, caseDbInstance);
577  }
578  }
579 
580  @Override
581  public boolean isSupported(Node node) {
582  this.file = this.getAbstractFileFromNode(node);
583  // Is supported if this node
584  // has correlatable content (File, BlackboardArtifact) OR
585  // other common files across datasources.
586 
587  if (EamDb.isEnabled()) {
588  return this.file != null
589  && this.file.getSize() > 0
590  && !getCorrelationAttributesFromNode(node).isEmpty();
591  } else {
592  return this.file != null
593  && this.file.getSize() > 0;
594  }
595  }
596 
597  @Override
598  @Messages({"DataContentViewerOtherCases.table.nodbconnection=Cannot connect to central repository database."})
599  public void setNode(Node node) {
600 
601  reset(); // reset the table to empty.
602  if (node == null) {
603  return;
604  }
605  //could be null
606  this.file = this.getAbstractFileFromNode(node);
607  populateTable(node);
608  }
609 
616  @Messages({"DataContentViewerOtherCases.table.isempty=There are no associated artifacts or files from other occurrences to display.",
617  "DataContentViewerOtherCases.table.noArtifacts=Correlation cannot be performed on the selected file."})
618  private void populateTable(Node node) {
619  String dataSourceName = "";
620  String deviceId = "";
621  try {
622  if (this.file != null) {
623  Content dataSource = this.file.getDataSource();
624  dataSourceName = dataSource.getName();
625  deviceId = Case.getCurrentCaseThrows().getSleuthkitCase().getDataSource(dataSource.getId()).getDeviceId();
626  }
627  } catch (TskException | NoCurrentCaseException ex) {
628  // do nothing.
629  // @@@ Review this behavior
630  }
631 
632  // get the attributes we can correlate on
633  correlationAttributes.addAll(getCorrelationAttributesFromNode(node));
634  for (CorrelationAttribute corAttr : correlationAttributes) {
635  Map<UniquePathKey, CorrelationAttributeInstance> corAttrInstances = new HashMap<>(0);
636 
637  // get correlation and reference set instances from DB
638  corAttrInstances.putAll(getCorrelatedInstances(corAttr, dataSourceName, deviceId));
639 
640  corAttrInstances.values().forEach((corAttrInstance) -> {
641  try {
642  CorrelationAttribute newCeArtifact = new CorrelationAttribute(
643  corAttr.getCorrelationType(),
644  corAttr.getCorrelationValue()
645  );
646  newCeArtifact.addInstance(corAttrInstance);
647  tableModel.addEamArtifact(newCeArtifact);
648  } catch (EamDbException ex) {
649  logger.log(Level.SEVERE, "Error creating correlation attribute", ex);
650  }
651  });
652  }
653 
654  if (correlationAttributes.isEmpty()) {
655  // @@@ BC: We should have a more descriptive message than this. Mention that the file didn't have a MD5, etc.
656  displayMessageOnTableStatusPanel(Bundle.DataContentViewerOtherCases_table_noArtifacts());
657  } else if (0 == tableModel.getRowCount()) {
658  displayMessageOnTableStatusPanel(Bundle.DataContentViewerOtherCases_table_isempty());
659  } else {
660  clearMessageOnTableStatusPanel();
661  setColumnWidths();
662  }
663  }
664 
665  private void setColumnWidths() {
666  for (int idx = 0; idx < tableModel.getColumnCount(); idx++) {
667  TableColumn column = otherCasesTable.getColumnModel().getColumn(idx);
668  int colWidth = tableModel.getColumnPreferredWidth(idx);
669  if (0 < colWidth) {
670  column.setPreferredWidth(colWidth);
671  }
672  }
673  }
674 
675  private void displayMessageOnTableStatusPanel(String message) {
676  tableStatusPanelLabel.setText(message);
677  tableStatusPanelLabel.setVisible(true);
678  }
679 
681  tableStatusPanelLabel.setVisible(false);
682  }
683 
689  @SuppressWarnings("unchecked")
690  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
691  private void initComponents() {
692 
693  rightClickPopupMenu = new javax.swing.JPopupMenu();
694  selectAllMenuItem = new javax.swing.JMenuItem();
695  exportToCSVMenuItem = new javax.swing.JMenuItem();
696  showCaseDetailsMenuItem = new javax.swing.JMenuItem();
697  showCommonalityMenuItem = new javax.swing.JMenuItem();
698  addCommentMenuItem = new javax.swing.JMenuItem();
699  CSVFileChooser = new javax.swing.JFileChooser();
700  otherCasesPanel = new javax.swing.JPanel();
701  tableContainerPanel = new javax.swing.JPanel();
702  tableScrollPane = new javax.swing.JScrollPane();
703  otherCasesTable = new javax.swing.JTable();
704  tableStatusPanel = new javax.swing.JPanel();
705  tableStatusPanelLabel = new javax.swing.JLabel();
706 
707  rightClickPopupMenu.addPopupMenuListener(new javax.swing.event.PopupMenuListener() {
708  public void popupMenuCanceled(javax.swing.event.PopupMenuEvent evt) {
709  }
710  public void popupMenuWillBecomeInvisible(javax.swing.event.PopupMenuEvent evt) {
711  }
712  public void popupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt) {
713  rightClickPopupMenuPopupMenuWillBecomeVisible(evt);
714  }
715  });
716 
717  org.openide.awt.Mnemonics.setLocalizedText(selectAllMenuItem, org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.selectAllMenuItem.text")); // NOI18N
718  rightClickPopupMenu.add(selectAllMenuItem);
719 
720  org.openide.awt.Mnemonics.setLocalizedText(exportToCSVMenuItem, org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.exportToCSVMenuItem.text")); // NOI18N
721  rightClickPopupMenu.add(exportToCSVMenuItem);
722 
723  org.openide.awt.Mnemonics.setLocalizedText(showCaseDetailsMenuItem, org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.showCaseDetailsMenuItem.text")); // NOI18N
724  rightClickPopupMenu.add(showCaseDetailsMenuItem);
725 
726  org.openide.awt.Mnemonics.setLocalizedText(showCommonalityMenuItem, org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.showCommonalityMenuItem.text")); // NOI18N
727  rightClickPopupMenu.add(showCommonalityMenuItem);
728 
729  org.openide.awt.Mnemonics.setLocalizedText(addCommentMenuItem, org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.addCommentMenuItem.text")); // NOI18N
730  rightClickPopupMenu.add(addCommentMenuItem);
731 
732  setMinimumSize(new java.awt.Dimension(1500, 10));
733  setOpaque(false);
734  setPreferredSize(new java.awt.Dimension(1500, 44));
735 
736  otherCasesPanel.setPreferredSize(new java.awt.Dimension(1500, 144));
737 
738  tableContainerPanel.setPreferredSize(new java.awt.Dimension(1500, 63));
739 
740  tableScrollPane.setPreferredSize(new java.awt.Dimension(1500, 30));
741 
742  otherCasesTable.setAutoCreateRowSorter(true);
743  otherCasesTable.setModel(tableModel);
744  otherCasesTable.setToolTipText(org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.table.toolTip.text")); // NOI18N
745  otherCasesTable.setComponentPopupMenu(rightClickPopupMenu);
746  otherCasesTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_INTERVAL_SELECTION);
747  tableScrollPane.setViewportView(otherCasesTable);
748 
749  tableStatusPanel.setPreferredSize(new java.awt.Dimension(1500, 16));
750 
751  tableStatusPanelLabel.setForeground(new java.awt.Color(255, 0, 51));
752 
753  javax.swing.GroupLayout tableStatusPanelLayout = new javax.swing.GroupLayout(tableStatusPanel);
754  tableStatusPanel.setLayout(tableStatusPanelLayout);
755  tableStatusPanelLayout.setHorizontalGroup(
756  tableStatusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
757  .addGap(0, 0, Short.MAX_VALUE)
758  .addGroup(tableStatusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
759  .addGroup(tableStatusPanelLayout.createSequentialGroup()
760  .addContainerGap()
761  .addComponent(tableStatusPanelLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 780, Short.MAX_VALUE)
762  .addContainerGap()))
763  );
764  tableStatusPanelLayout.setVerticalGroup(
765  tableStatusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
766  .addGap(0, 16, Short.MAX_VALUE)
767  .addGroup(tableStatusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
768  .addGroup(tableStatusPanelLayout.createSequentialGroup()
769  .addComponent(tableStatusPanelLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE)
770  .addGap(0, 0, Short.MAX_VALUE)))
771  );
772 
773  javax.swing.GroupLayout tableContainerPanelLayout = new javax.swing.GroupLayout(tableContainerPanel);
774  tableContainerPanel.setLayout(tableContainerPanelLayout);
775  tableContainerPanelLayout.setHorizontalGroup(
776  tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
777  .addComponent(tableScrollPane, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
778  .addComponent(tableStatusPanel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
779  );
780  tableContainerPanelLayout.setVerticalGroup(
781  tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
782  .addGroup(tableContainerPanelLayout.createSequentialGroup()
783  .addComponent(tableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
784  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
785  .addComponent(tableStatusPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
786  .addContainerGap())
787  );
788 
789  javax.swing.GroupLayout otherCasesPanelLayout = new javax.swing.GroupLayout(otherCasesPanel);
790  otherCasesPanel.setLayout(otherCasesPanelLayout);
791  otherCasesPanelLayout.setHorizontalGroup(
792  otherCasesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
793  .addGap(0, 1500, Short.MAX_VALUE)
794  .addGroup(otherCasesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
795  .addComponent(tableContainerPanel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
796  );
797  otherCasesPanelLayout.setVerticalGroup(
798  otherCasesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
799  .addGap(0, 60, Short.MAX_VALUE)
800  .addGroup(otherCasesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
801  .addGroup(otherCasesPanelLayout.createSequentialGroup()
802  .addComponent(tableContainerPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 52, Short.MAX_VALUE)
803  .addGap(0, 0, 0)))
804  );
805 
806  javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
807  this.setLayout(layout);
808  layout.setHorizontalGroup(
809  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
810  .addComponent(otherCasesPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
811  );
812  layout.setVerticalGroup(
813  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
814  .addComponent(otherCasesPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 52, Short.MAX_VALUE)
815  );
816  }// </editor-fold>//GEN-END:initComponents
817 
818  private void rightClickPopupMenuPopupMenuWillBecomeVisible(javax.swing.event.PopupMenuEvent evt) {//GEN-FIRST:event_rightClickPopupMenuPopupMenuWillBecomeVisible
819  boolean addCommentMenuItemVisible = false;
820 
821  if (EamDbUtil.useCentralRepo() && otherCasesTable.getSelectedRowCount() == 1) {
822  int rowIndex = otherCasesTable.getSelectedRow();
823  CorrelationAttribute selectedAttribute = (CorrelationAttribute) tableModel.getRow(rowIndex);
824  if (selectedAttribute.getInstances().get(0).isDatabaseInstance()
825  && selectedAttribute.getCorrelationType().getId() == CorrelationAttribute.FILES_TYPE_ID) {
826  addCommentMenuItemVisible = true;
827  }
828  }
829 
830  addCommentMenuItem.setVisible(addCommentMenuItemVisible);
831  }//GEN-LAST:event_rightClickPopupMenuPopupMenuWillBecomeVisible
832 
833  // Variables declaration - do not modify//GEN-BEGIN:variables
834  private javax.swing.JFileChooser CSVFileChooser;
835  private javax.swing.JMenuItem addCommentMenuItem;
836  private javax.swing.JMenuItem exportToCSVMenuItem;
837  private javax.swing.JPanel otherCasesPanel;
838  private javax.swing.JTable otherCasesTable;
839  private javax.swing.JPopupMenu rightClickPopupMenu;
840  private javax.swing.JMenuItem selectAllMenuItem;
841  private javax.swing.JMenuItem showCaseDetailsMenuItem;
842  private javax.swing.JMenuItem showCommonalityMenuItem;
843  private javax.swing.JPanel tableContainerPanel;
844  private javax.swing.JScrollPane tableScrollPane;
845  private javax.swing.JPanel tableStatusPanel;
846  private javax.swing.JLabel tableStatusPanelLabel;
847  // End of variables declaration//GEN-END:variables
848 
853  static final class UniquePathKey {
854 
855  private final String dataSourceID;
856  private final String filePath;
857 
858  UniquePathKey(String theDataSource, String theFilePath) {
859  super();
860  dataSourceID = theDataSource;
861  filePath = theFilePath.toLowerCase();
862  }
863 
868  String getDataSourceID() {
869  return dataSourceID;
870  }
871 
876  String getFilePath() {
877  return filePath;
878  }
879 
880  @Override
881  public boolean equals(Object other) {
882  if (other instanceof UniquePathKey) {
883  return ((UniquePathKey) other).getDataSourceID().equals(dataSourceID) && ((UniquePathKey) other).getFilePath().equals(filePath);
884  }
885  return false;
886  }
887 
888  @Override
889  public int hashCode() {
890  //int hash = 7;
891  //hash = 67 * hash + this.dataSourceID.hashCode();
892  //hash = 67 * hash + this.filePath.hashCode();
893  return Objects.hash(dataSourceID, filePath);
894  }
895  }
896 
897 }
int getFrequencyPercentage(CorrelationAttribute corAttr)
static CorrelationDataSource fromTSKDataSource(CorrelationCase correlationCase, Content dataSource)
void addOrUpdateAttributeInstance(final Case autopsyCase, Map< UniquePathKey, CorrelationAttributeInstance > artifactInstances, AbstractFile newFile)
void addInstance(CorrelationAttributeInstance artifactInstance)
List< CorrelationAttributeInstance > getArtifactInstancesByTypeValue(CorrelationAttribute.Type aType, String value)
List< AbstractFile > addCaseDbMatches(CorrelationAttribute corAttr, Case openCase)
static AddEditCentralRepoCommentAction createAddEditCommentAction(CorrelationAttribute correlationAttribute)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
List< CorrelationAttribute.Type > getDefinedCorrelationTypes()
Map< UniquePathKey, CorrelationAttributeInstance > getCorrelatedInstances(CorrelationAttribute corAttr, String dataSourceName, String deviceId)
static List< CorrelationAttribute > getCorrelationAttributeFromBlackboardArtifact(BlackboardArtifact bbArtifact, boolean addInstanceDetails, boolean checkEnabled)

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