Autopsy  4.20.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
DataSourceBrowser.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2019-2021 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.datasourcesummary.ui;
20 
22 import java.awt.Cursor;
24 import java.awt.EventQueue;
25 import java.beans.PropertyVetoException;
26 import javax.swing.ListSelectionModel;
27 import org.netbeans.swing.outline.DefaultOutlineModel;
28 import org.netbeans.swing.outline.Outline;
29 import org.openide.explorer.ExplorerManager;
30 import java.util.ArrayList;
31 import java.util.Collections;
32 import java.util.List;
33 import java.util.Map;
34 import java.util.Observer;
35 import java.util.logging.Level;
37 import javax.swing.event.ListSelectionListener;
38 import org.openide.nodes.Node;
42 import static javax.swing.SwingConstants.RIGHT;
43 import javax.swing.SwingUtilities;
44 import javax.swing.SwingWorker;
45 import javax.swing.table.TableColumn;
46 import org.sleuthkit.datamodel.DataSource;
47 import org.sleuthkit.datamodel.IngestJobInfo;
48 import org.sleuthkit.datamodel.SleuthkitCase;
49 import org.sleuthkit.datamodel.TskCoreException;
50 
55 final class DataSourceBrowser extends javax.swing.JPanel implements ExplorerManager.Provider {
56 
57  private static final long serialVersionUID = 1L;
58  private static final Logger logger = Logger.getLogger(DataSourceBrowser.class.getName());
59  private static final int COUNT_COLUMN_WIDTH = 20;
60  private static final int INGEST_STATUS_WIDTH = 50;
61  private static final int USAGE_COLUMN_WIDTH = 110;
62  private static final int DATA_SOURCE_COLUMN_WIDTH = 280;
63  private final Outline outline;
64  private final org.openide.explorer.view.OutlineView outlineView;
65  private final ExplorerManager explorerManager;
66  private final List<DataSourceSummary> dataSourceSummaryList;
67  private final RightAlignedTableCellRenderer rightAlignedRenderer = new RightAlignedTableCellRenderer();
68  private SwingWorker<Void, Void> rootNodeWorker = null;
69 
73  DataSourceBrowser() {
74  initComponents();
75  rightAlignedRenderer.setHorizontalAlignment(RIGHT);
76  explorerManager = new ExplorerManager();
77  outlineView = new org.openide.explorer.view.OutlineView();
78  this.setVisible(true);
79  outlineView.setPropertyColumns(
80  Bundle.DataSourceSummaryNode_column_status_header(), Bundle.DataSourceSummaryNode_column_status_header(),
81  Bundle.DataSourceSummaryNode_column_type_header(), Bundle.DataSourceSummaryNode_column_type_header(),
82  Bundle.DataSourceSummaryNode_column_files_header(), Bundle.DataSourceSummaryNode_column_files_header(),
83  Bundle.DataSourceSummaryNode_column_results_header(), Bundle.DataSourceSummaryNode_column_results_header(),
84  Bundle.DataSourceSummaryNode_column_tags_header(), Bundle.DataSourceSummaryNode_column_tags_header());
85  outline = outlineView.getOutline();
86  outline.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
87  dataSourceSummaryList = new ArrayList<>();
88  outline.setRootVisible(false);
89  add(outlineView, java.awt.BorderLayout.CENTER);
90  ((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel(Bundle.DataSourceSummaryNode_column_dataSourceName_header());
91  for (TableColumn column : Collections.list(outline.getColumnModel().getColumns())) {
92  if (column.getHeaderValue().toString().equals(Bundle.DataSourceSummaryNode_column_files_header())
93  || column.getHeaderValue().toString().equals(Bundle.DataSourceSummaryNode_column_results_header())
94  || column.getHeaderValue().toString().equals(Bundle.DataSourceSummaryNode_column_tags_header())) {
95  column.setCellRenderer(rightAlignedRenderer);
96  column.setPreferredWidth(COUNT_COLUMN_WIDTH);
97  } else if (column.getHeaderValue().toString().equals(Bundle.DataSourceSummaryNode_column_type_header())) {
98  column.setPreferredWidth(USAGE_COLUMN_WIDTH);
99  } else if (column.getHeaderValue().toString().equals(Bundle.DataSourceSummaryNode_column_status_header())) {
100  column.setPreferredWidth(INGEST_STATUS_WIDTH);
101  } else {
102  column.setPreferredWidth(DATA_SOURCE_COLUMN_WIDTH);
103  }
104  }
105  this.setVisible(true);
106  }
107 
116  void selectDataSource(Long dataSourceId) {
117  EventQueue.invokeLater(() -> {
118  if (dataSourceId != null) {
119  for (Node node : explorerManager.getRootContext().getChildren().getNodes()) {
120  if (node instanceof DataSourceSummaryEntryNode && ((DataSourceSummaryEntryNode) node).getDataSource().getId() == dataSourceId) {
121  try {
122  explorerManager.setExploredContextAndSelection(node, new Node[]{node});
123  return;
124  } catch (PropertyVetoException ex) {
125  logger.log(Level.WARNING, "Failed to select the datasource in the explorer view", ex); //NON-NLS
126  }
127  }
128  }
129  }
130  //if no data source was selected and there are data sources to select select the first one
131  if (explorerManager.getRootContext().getChildren().getNodes().length > 0) {
132  outline.getSelectionModel().setSelectionInterval(0, 0);
133  }
134  });
135  }
136 
143  void addObserver(Observer observer) {
144  ((DataSourceSummaryNode) explorerManager.getRootContext()).addObserver(observer);
145  }
146 
154  private List<DataSourceSummary> getDataSourceSummaryList(Map<Long, String> usageMap, Map<Long, Long> fileCountsMap) {
155  List<DataSourceSummary> summaryList = new ArrayList<>();
156 
157  final Map<Long, Long> artifactCountsMap = CaseDataSourcesSummary.getCountsOfArtifacts();
158  final Map<Long, Long> tagCountsMap = CaseDataSourcesSummary.getCountsOfTags();
159  try {
160  SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
161  for (DataSource dataSource : skCase.getDataSources()) {
162  summaryList.add(new DataSourceSummary(dataSource, usageMap.get(dataSource.getId()),
163  fileCountsMap.get(dataSource.getId()), artifactCountsMap.get(dataSource.getId()), tagCountsMap.get(dataSource.getId())));
164  }
165  } catch (TskCoreException | NoCurrentCaseException ex) {
166  logger.log(Level.WARNING, "Unable to datasources or their counts, providing empty results", ex);
167  }
168  return summaryList;
169  }
170 
176  void addListSelectionListener(ListSelectionListener listener) {
177  outline.getSelectionModel().addListSelectionListener(listener);
178  }
179 
185  DataSource getSelectedDataSource() {
186  Node selectedNode[] = explorerManager.getSelectedNodes();
187  if (selectedNode.length == 1 && selectedNode[0] instanceof DataSourceSummaryEntryNode) {
188  return ((DataSourceSummaryEntryNode) selectedNode[0]).getDataSource();
189  }
190  return null;
191  }
192 
200  void refresh(long dataSourceId, IngestJobInfo.IngestJobStatusType newStatus) {
201 
202  //attempt to update the status of any datasources that had status which was STARTED
203  for (DataSourceSummary summary : dataSourceSummaryList) {
204  if (summary.getDataSource().getId() == dataSourceId) {
205  summary.setIngestStatus(newStatus);
206  }
207  }
208  //figure out which nodes were previously selected
209  Node[] selectedNodes = explorerManager.getSelectedNodes();
210  SwingUtilities.invokeLater(() -> {
211  explorerManager.setRootContext(new DataSourceSummaryNode(dataSourceSummaryList));
212  List<Node> nodesToSelect = new ArrayList<>();
213  for (Node node : explorerManager.getRootContext().getChildren().getNodes()) {
214  if (node instanceof DataSourceSummaryEntryNode) {
215  //there should only be one selected node as multi-select is disabled
216  for (Node selectedNode : selectedNodes) {
217  if (((DataSourceSummaryEntryNode) node).getDataSource().equals(((DataSourceSummaryEntryNode) selectedNode).getDataSource())) {
218  nodesToSelect.add(node);
219  }
220  }
221  }
222  }
223  //reselect the previously selected Nodes
224  try {
225  explorerManager.setSelectedNodes(nodesToSelect.toArray(new Node[nodesToSelect.size()]));
226  } catch (PropertyVetoException ex) {
227  logger.log(Level.WARNING, "Error selecting previously selected nodes", ex);
228  }
229 
230  });
231 
232  }
233 
239  @SuppressWarnings("unchecked")
240  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
241  private void initComponents() {
242 
243  setLayout(new java.awt.BorderLayout());
244  }// </editor-fold>//GEN-END:initComponents
245 
246  @Override
247  public ExplorerManager getExplorerManager() {
248  return explorerManager;
249  }
250 
260  void populateBrowser(DataSourceSummaryDialog dsSummaryDialog, Long selectedDataSourceId) {
261  dsSummaryDialog.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
262  if (rootNodeWorker != null && !rootNodeWorker.isDone()) {
263  rootNodeWorker.cancel(true);
264  }
265 
266  dataSourceSummaryList.clear();
267  rootNodeWorker = new SwingWorker<Void, Void>() {
268  @Override
269  protected Void doInBackground() throws Exception {
270  Map<Long, String> usageMap = CaseDataSourcesSummary.getDataSourceTypes();
271  Map<Long, Long> fileCountsMap = CaseDataSourcesSummary.getCountsOfFiles();
272  dataSourceSummaryList.addAll(getDataSourceSummaryList(usageMap, fileCountsMap));
273  return null;
274  }
275 
276  @Override
277  protected void done() {
278  explorerManager.setRootContext(new DataSourceSummaryNode(dataSourceSummaryList));
279  selectDataSource(selectedDataSourceId);
280  addObserver(dsSummaryDialog);
281  dsSummaryDialog.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
282  }
283  };
284  rootNodeWorker.execute();
285  }
286 
291  void cancel() {
292  if (rootNodeWorker != null && !rootNodeWorker.isDone()) {
293  rootNodeWorker.cancel(true);
294  }
295  }
296 
297  // Variables declaration - do not modify//GEN-BEGIN:variables
298  // End of variables declaration//GEN-END:variables
299 }

Copyright © 2012-2022 Basis Technology. Generated on: Tue Aug 1 2023
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.