Autopsy  4.19.3
Graphical digital forensics platform for The Sleuth Kit and other tools.
PortableCaseTagsListPanel.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 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.report.infrastructure;
20 
22 import java.awt.Component;
23 import java.awt.event.ItemEvent;
24 import java.awt.event.ItemListener;
25 import java.awt.event.MouseAdapter;
26 import java.awt.event.MouseEvent;
27 import java.sql.ResultSet;
28 import java.sql.SQLException;
29 import java.util.ArrayList;
30 import java.util.HashMap;
31 import java.util.LinkedHashMap;
32 import java.util.List;
33 import java.util.Map;
34 import java.util.logging.Level;
35 import javax.swing.JCheckBox;
36 import javax.swing.JLabel;
37 import javax.swing.JList;
38 import javax.swing.ListCellRenderer;
39 import javax.swing.ListModel;
40 import javax.swing.event.ListDataListener;
41 import org.openide.util.NbBundle;
45 import org.sleuthkit.datamodel.CaseDbAccessManager;
46 import org.sleuthkit.datamodel.TagName;
47 import org.sleuthkit.datamodel.TskCoreException;
48 
52 @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
53 class PortableCaseTagsListPanel extends javax.swing.JPanel {
54 
55  private List<TagName> tagNames;
56  private final Map<String, Boolean> tagNameSelections = new LinkedHashMap<>();
57  private final TagNamesListModel tagsNamesListModel = new TagNamesListModel();
58  private final TagsNamesListCellRenderer tagsNamesRenderer = new TagsNamesListCellRenderer();
59  private final Map<String, Long> tagCounts = new HashMap<>();
60 
61  private final ReportWizardPortableCaseOptionsPanel wizPanel;
62  private final PortableCaseReportModuleSettings settings;
63  private final boolean useCaseSpecificData;
64 
68  PortableCaseTagsListPanel(ReportWizardPortableCaseOptionsPanel wizPanel, PortableCaseReportModuleSettings options, boolean useCaseSpecificData) {
69  this.wizPanel = wizPanel;
70  this.useCaseSpecificData = useCaseSpecificData;
71  this.settings = options;
72  initComponents();
73  customizeComponents();
74  // update tag selection
75  jAllTagsCheckBox.setSelected(settings.areAllTagsSelected());
76  tagNamesListBox.setEnabled(!jAllTagsCheckBox.isSelected());
77  selectButton.setEnabled(!jAllTagsCheckBox.isSelected());
78  deselectButton.setEnabled(!jAllTagsCheckBox.isSelected());
79  selectAllTags(jAllTagsCheckBox.isSelected());
80 
81  this.jAllTagsCheckBox.addItemListener(new ItemListener() {
82  @Override
83  public void itemStateChanged(ItemEvent e) {
84  tagNamesListBox.setEnabled(!jAllTagsCheckBox.isSelected());
85  selectButton.setEnabled(!jAllTagsCheckBox.isSelected());
86  deselectButton.setEnabled(!jAllTagsCheckBox.isSelected());
87  selectAllTags(jAllTagsCheckBox.isSelected());
88  }
89  });
90  }
91 
92  @NbBundle.Messages({
93  "PortableCaseTagsListPanel.error.errorTitle=Error getting tag names for case",
94  "PortableCaseTagsListPanel.error.noOpenCase=There is no case open",
95  "PortableCaseTagsListPanel.error.errorLoadingTags=Error loading tags",
96  })
97  private void customizeComponents() {
98  // Get the tag names in use for the current case.
99  tagNames = new ArrayList<>();
100  Map<Long, Long> tagCountsByID = new HashMap<>();
101  try {
102  // only try to load tag names if we are displaying case specific data, otherwise
103  // we will be displaying case specific data in command line wizard if there is
104  // a case open in the background
105  if (useCaseSpecificData) {
106  tagNames = Case.getCurrentCaseThrows().getServices().getTagsManager().getTagNamesInUse();
107 
108  // Get the counts for each tag ID
109  String query = "tag_name_id, count(1) AS tag_count "
110  + "FROM ("
111  + "SELECT tag_name_id FROM content_tags UNION ALL SELECT tag_name_id FROM blackboard_artifact_tags"
112  + ") tag_ids GROUP BY tag_name_id"; // NON-NLS
113  GetTagCountsCallback callback = new GetTagCountsCallback();
114  Case.getCurrentCaseThrows().getSleuthkitCase().getCaseDbAccessManager().select(query, callback);
115  tagCountsByID = callback.getTagCountMap();
116  }
117 
118  // Mark the tag names as unselected. Note that tagNameSelections is a
119  // LinkedHashMap so that order is preserved and the tagNames and tagNameSelections
120  // containers are "parallel" containers.
121  for (TagName tagName : tagNames) {
122  tagNameSelections.put(tagName.getDisplayName(), Boolean.FALSE);
123  if (tagCountsByID.containsKey(tagName.getId())) {
124  tagCounts.put(tagName.getDisplayName(), tagCountsByID.get(tagName.getId()));
125  } else {
126  tagCounts.put(tagName.getDisplayName(), 0L);
127  }
128  }
129  } catch (TskCoreException ex) {
130  Logger.getLogger(ReportWizardPortableCaseOptionsVisualPanel.class.getName()).log(Level.SEVERE, "Failed to get tag names", ex); // NON-NLS
131  } catch (NoCurrentCaseException ex) {
132  // There may not be a case open when configuring report modules for Command Line execution
133  Logger.getLogger(ReportWizardPortableCaseOptionsVisualPanel.class.getName()).log(Level.WARNING, "Exception while getting open case.", ex); // NON-NLS
134  }
135 
136  // Set up the tag names JList component to be a collection of check boxes
137  // for selecting tag names. The mouse click listener updates tagNameSelections
138  // to reflect user choices.
139  tagNamesListBox.setModel(tagsNamesListModel);
140  tagNamesListBox.setCellRenderer(tagsNamesRenderer);
141  tagNamesListBox.setVisibleRowCount(-1);
142  tagNamesListBox.addMouseListener(new MouseAdapter() {
143  @Override
144  public void mousePressed(MouseEvent evt) {
145  JList<?> list = (JList) evt.getSource();
146  int index = list.locationToIndex(evt.getPoint());
147  if (index > -1) {
148  String value = tagsNamesListModel.getElementAt(index);
149  tagNameSelections.put(value, !tagNameSelections.get(value));
150  list.repaint();
151  updateTagList();
152  }
153  }
154  });
155  }
156 
160  private void updateTagList() {
161  settings.updateTagNames(getSelectedTagNames());
162  settings.setAllTagsSelected(jAllTagsCheckBox.isSelected());
163  wizPanel.setFinish(settings.isValid());
164  }
165 
169  private class TagNamesListModel implements ListModel<String> {
170 
171  @Override
172  public int getSize() {
173  return tagNames.size();
174  }
175 
176  @Override
177  public String getElementAt(int index) {
178  return tagNames.get(index).getDisplayName();
179  }
180 
181  @Override
182  public void addListDataListener(ListDataListener l) {
183  // Nothing to do
184  }
185 
186  @Override
187  public void removeListDataListener(ListDataListener l) {
188  // Nothing to do
189  }
190  }
191 
195  private class TagsNamesListCellRenderer extends JCheckBox implements ListCellRenderer<String> {
196  private static final long serialVersionUID = 1L;
197 
198  @Override
199  public Component getListCellRendererComponent(JList<? extends String> list, String value, int index, boolean isSelected, boolean cellHasFocus) {
200  if (value != null) {
201  setEnabled(list.isEnabled());
202  setSelected(tagNameSelections.get(value));
203  setFont(list.getFont());
204  setBackground(list.getBackground());
205  setForeground(list.getForeground());
206  String text = value + " (" + tagCounts.get(value) + ")";
207  setText(text);
208  setToolTipText(text);
209  return this;
210  }
211  return new JLabel();
212  }
213  }
214 
220  private List<TagName> getSelectedTagNames() {
221  List<TagName> selectedTagNames = new ArrayList<>();
222  for (TagName tagName : tagNames) {
223  if (tagNameSelections.get(tagName.getDisplayName())) {
224  selectedTagNames.add(tagName);
225  }
226  }
227  return selectedTagNames;
228  }
229 
233  static class GetTagCountsCallback implements CaseDbAccessManager.CaseDbAccessQueryCallback {
234 
235  private static final Logger logger = Logger.getLogger(GetTagCountsCallback.class.getName());
236  private final Map<Long, Long> tagCounts = new HashMap<>();
237 
238  @Override
239  public void process(ResultSet rs) {
240  try {
241  while (rs.next()) {
242  try {
243  Long tagCount = rs.getLong("tag_count"); // NON-NLS
244  Long tagID = rs.getLong("tag_name_id"); // NON-NLS
245 
246  tagCounts.put(tagID, tagCount);
247 
248  } catch (SQLException ex) {
249  logger.log(Level.WARNING, "Unable to get data_source_obj_id or value from result set", ex); // NON-NLS
250  }
251  }
252  } catch (SQLException ex) {
253  logger.log(Level.WARNING, "Failed to get next result for values by datasource", ex); // NON-NLS
254  }
255  }
256 
262  Map<Long, Long> getTagCountMap() {
263  return tagCounts;
264  }
265  }
266 
272  @SuppressWarnings("unchecked")
273  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
274  private void initComponents() {
275 
276  jPanel1 = new javax.swing.JPanel();
277  jScrollPane1 = new javax.swing.JScrollPane();
278  tagNamesListBox = new javax.swing.JList<>();
279  descLabel = new javax.swing.JLabel();
280  selectButton = new javax.swing.JButton();
281  deselectButton = new javax.swing.JButton();
282  jAllTagsCheckBox = new javax.swing.JCheckBox();
283 
284  jScrollPane1.setViewportView(tagNamesListBox);
285 
286  org.openide.awt.Mnemonics.setLocalizedText(descLabel, org.openide.util.NbBundle.getMessage(PortableCaseTagsListPanel.class, "PortableCaseTagsListPanel.descLabel.text")); // NOI18N
287 
288  org.openide.awt.Mnemonics.setLocalizedText(selectButton, org.openide.util.NbBundle.getMessage(PortableCaseTagsListPanel.class, "PortableCaseTagsListPanel.selectButton.text")); // NOI18N
289  selectButton.setMaximumSize(new java.awt.Dimension(87, 23));
290  selectButton.setMinimumSize(new java.awt.Dimension(87, 23));
291  selectButton.addActionListener(new java.awt.event.ActionListener() {
292  public void actionPerformed(java.awt.event.ActionEvent evt) {
293  selectButtonActionPerformed(evt);
294  }
295  });
296 
297  org.openide.awt.Mnemonics.setLocalizedText(deselectButton, org.openide.util.NbBundle.getMessage(PortableCaseTagsListPanel.class, "PortableCaseTagsListPanel.deselectButton.text")); // NOI18N
298  deselectButton.addActionListener(new java.awt.event.ActionListener() {
299  public void actionPerformed(java.awt.event.ActionEvent evt) {
300  deselectButtonActionPerformed(evt);
301  }
302  });
303 
304  org.openide.awt.Mnemonics.setLocalizedText(jAllTagsCheckBox, org.openide.util.NbBundle.getMessage(PortableCaseTagsListPanel.class, "PortableCaseTagsListPanel.jAllTagsCheckBox.text")); // NOI18N
305  jAllTagsCheckBox.addActionListener(new java.awt.event.ActionListener() {
306  public void actionPerformed(java.awt.event.ActionEvent evt) {
307  jAllTagsCheckBoxActionPerformed(evt);
308  }
309  });
310 
311  javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
312  jPanel1.setLayout(jPanel1Layout);
313  jPanel1Layout.setHorizontalGroup(
314  jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
315  .addGroup(jPanel1Layout.createSequentialGroup()
316  .addContainerGap()
317  .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
318  .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
319  .addGroup(jPanel1Layout.createSequentialGroup()
320  .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
321  .addComponent(descLabel)
322  .addGroup(jPanel1Layout.createSequentialGroup()
323  .addComponent(selectButton, javax.swing.GroupLayout.PREFERRED_SIZE, 96, javax.swing.GroupLayout.PREFERRED_SIZE)
324  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
325  .addComponent(deselectButton))
326  .addComponent(jAllTagsCheckBox))
327  .addGap(0, 0, Short.MAX_VALUE)))
328  .addContainerGap())
329  );
330  jPanel1Layout.setVerticalGroup(
331  jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
332  .addGroup(jPanel1Layout.createSequentialGroup()
333  .addComponent(descLabel)
334  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
335  .addComponent(jAllTagsCheckBox)
336  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
337  .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 163, Short.MAX_VALUE)
338  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
339  .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
340  .addComponent(selectButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
341  .addComponent(deselectButton)))
342  );
343 
344  javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
345  this.setLayout(layout);
346  layout.setHorizontalGroup(
347  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
348  .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
349  );
350  layout.setVerticalGroup(
351  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
352  .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
353  );
354  }// </editor-fold>//GEN-END:initComponents
355 
356  private void deselectButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deselectButtonActionPerformed
357  selectAllTags(false);
358  }//GEN-LAST:event_deselectButtonActionPerformed
359 
360  private void selectButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_selectButtonActionPerformed
361  selectAllTags(true);
362  }//GEN-LAST:event_selectButtonActionPerformed
363 
364  private void jAllTagsCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jAllTagsCheckBoxActionPerformed
365  selectAllTags(true);
366  }//GEN-LAST:event_jAllTagsCheckBoxActionPerformed
367 
368  private void selectAllTags(boolean select) {
369  Boolean state = Boolean.TRUE;
370  if (!select) {
371  state = Boolean.FALSE;
372  }
373  for (TagName tagName : tagNames) {
374  tagNameSelections.put(tagName.getDisplayName(), state);
375  }
376  updateTagList();
377  tagNamesListBox.repaint();
378  }
379 
380  // Variables declaration - do not modify//GEN-BEGIN:variables
381  private javax.swing.JLabel descLabel;
382  private javax.swing.JButton deselectButton;
383  private javax.swing.JCheckBox jAllTagsCheckBox;
384  private javax.swing.JPanel jPanel1;
385  private javax.swing.JScrollPane jScrollPane1;
386  private javax.swing.JButton selectButton;
387  private javax.swing.JList<String> tagNamesListBox;
388  // End of variables declaration//GEN-END:variables
389 }
Component getListCellRendererComponent(JList<?extends String > list, String value, int index, boolean isSelected, boolean cellHasFocus)

Copyright © 2012-2022 Basis Technology. Generated on: Wed Oct 5 2022
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.