19 package org.sleuthkit.autopsy.datasourcesummary.ui;
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;
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;
55 final class DataSourceBrowser
extends javax.swing.JPanel implements ExplorerManager.Provider {
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;
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);
102 column.setPreferredWidth(DATA_SOURCE_COLUMN_WIDTH);
105 this.setVisible(
true);
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) {
122 explorerManager.setExploredContextAndSelection(node,
new Node[]{node});
124 }
catch (PropertyVetoException ex) {
125 logger.log(Level.WARNING,
"Failed to select the datasource in the explorer view", ex);
131 if (explorerManager.getRootContext().getChildren().getNodes().length > 0) {
132 outline.getSelectionModel().setSelectionInterval(0, 0);
143 void addObserver(Observer observer) {
144 ((DataSourceSummaryNode) explorerManager.getRootContext()).addObserver(observer);
154 private List<DataSourceSummary> getDataSourceSummaryList(Map<Long, String> usageMap, Map<Long, Long> fileCountsMap) {
155 List<DataSourceSummary> summaryList =
new ArrayList<>();
157 final Map<Long, Long> artifactCountsMap = CaseDataSourcesSummary.getCountsOfArtifacts();
158 final Map<Long, Long> tagCountsMap = CaseDataSourcesSummary.getCountsOfTags();
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())));
165 }
catch (TskCoreException | NoCurrentCaseException ex) {
166 logger.log(Level.WARNING,
"Unable to datasources or their counts, providing empty results", ex);
176 void addListSelectionListener(ListSelectionListener listener) {
177 outline.getSelectionModel().addListSelectionListener(listener);
185 DataSource getSelectedDataSource() {
186 Node selectedNode[] = explorerManager.getSelectedNodes();
187 if (selectedNode.length == 1 && selectedNode[0] instanceof DataSourceSummaryEntryNode) {
188 return ((DataSourceSummaryEntryNode) selectedNode[0]).getDataSource();
200 void refresh(
long dataSourceId, IngestJobInfo.IngestJobStatusType newStatus) {
203 for (DataSourceSummary summary : dataSourceSummaryList) {
204 if (summary.getDataSource().getId() == dataSourceId) {
205 summary.setIngestStatus(newStatus);
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) {
216 for (Node selectedNode : selectedNodes) {
217 if (((DataSourceSummaryEntryNode) node).getDataSource().equals(((DataSourceSummaryEntryNode) selectedNode).getDataSource())) {
218 nodesToSelect.add(node);
225 explorerManager.setSelectedNodes(nodesToSelect.toArray(
new Node[nodesToSelect.size()]));
226 }
catch (PropertyVetoException ex) {
227 logger.log(Level.WARNING,
"Error selecting previously selected nodes", ex);
239 @SuppressWarnings(
"unchecked")
241 private
void initComponents() {
243 setLayout(
new java.awt.BorderLayout());
247 public ExplorerManager getExplorerManager() {
248 return explorerManager;
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);
266 dataSourceSummaryList.clear();
267 rootNodeWorker =
new SwingWorker<Void, Void>() {
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));
277 protected void done() {
278 explorerManager.setRootContext(
new DataSourceSummaryNode(dataSourceSummaryList));
279 selectDataSource(selectedDataSourceId);
280 addObserver(dsSummaryDialog);
281 dsSummaryDialog.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
284 rootNodeWorker.execute();
292 if (rootNodeWorker != null && !rootNodeWorker.isDone()) {
293 rootNodeWorker.cancel(
true);