Autopsy  4.14.0
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  setText(value + " (" + tagCounts.get(value) + ")"); // NON-NLS
207  return this;
208  }
209  return new JLabel();
210  }
211  }
212 
218  private List<TagName> getSelectedTagNames() {
219  List<TagName> selectedTagNames = new ArrayList<>();
220  for (TagName tagName : tagNames) {
221  if (tagNameSelections.get(tagName.getDisplayName())) {
222  selectedTagNames.add(tagName);
223  }
224  }
225  return selectedTagNames;
226  }
227 
231  static class GetTagCountsCallback implements CaseDbAccessManager.CaseDbAccessQueryCallback {
232 
233  private static final Logger logger = Logger.getLogger(GetTagCountsCallback.class.getName());
234  private final Map<Long, Long> tagCounts = new HashMap<>();
235 
236  @Override
237  public void process(ResultSet rs) {
238  try {
239  while (rs.next()) {
240  try {
241  Long tagCount = rs.getLong("tag_count"); // NON-NLS
242  Long tagID = rs.getLong("tag_name_id"); // NON-NLS
243 
244  tagCounts.put(tagID, tagCount);
245 
246  } catch (SQLException ex) {
247  logger.log(Level.WARNING, "Unable to get data_source_obj_id or value from result set", ex); // NON-NLS
248  }
249  }
250  } catch (SQLException ex) {
251  logger.log(Level.WARNING, "Failed to get next result for values by datasource", ex); // NON-NLS
252  }
253  }
254 
260  Map<Long, Long> getTagCountMap() {
261  return tagCounts;
262  }
263  }
264 
270  @SuppressWarnings("unchecked")
271  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
272  private void initComponents() {
273 
274  jPanel1 = new javax.swing.JPanel();
275  jScrollPane1 = new javax.swing.JScrollPane();
276  tagNamesListBox = new javax.swing.JList<>();
277  descLabel = new javax.swing.JLabel();
278  selectButton = new javax.swing.JButton();
279  deselectButton = new javax.swing.JButton();
280  jAllTagsCheckBox = new javax.swing.JCheckBox();
281 
282  jScrollPane1.setViewportView(tagNamesListBox);
283 
284  org.openide.awt.Mnemonics.setLocalizedText(descLabel, org.openide.util.NbBundle.getMessage(PortableCaseTagsListPanel.class, "PortableCaseTagsListPanel.descLabel.text")); // NOI18N
285 
286  org.openide.awt.Mnemonics.setLocalizedText(selectButton, org.openide.util.NbBundle.getMessage(PortableCaseTagsListPanel.class, "PortableCaseTagsListPanel.selectButton.text")); // NOI18N
287  selectButton.setMaximumSize(new java.awt.Dimension(87, 23));
288  selectButton.setMinimumSize(new java.awt.Dimension(87, 23));
289  selectButton.addActionListener(new java.awt.event.ActionListener() {
290  public void actionPerformed(java.awt.event.ActionEvent evt) {
291  selectButtonActionPerformed(evt);
292  }
293  });
294 
295  org.openide.awt.Mnemonics.setLocalizedText(deselectButton, org.openide.util.NbBundle.getMessage(PortableCaseTagsListPanel.class, "PortableCaseTagsListPanel.deselectButton.text")); // NOI18N
296  deselectButton.addActionListener(new java.awt.event.ActionListener() {
297  public void actionPerformed(java.awt.event.ActionEvent evt) {
298  deselectButtonActionPerformed(evt);
299  }
300  });
301 
302  org.openide.awt.Mnemonics.setLocalizedText(jAllTagsCheckBox, org.openide.util.NbBundle.getMessage(PortableCaseTagsListPanel.class, "PortableCaseTagsListPanel.jAllTagsCheckBox.text")); // NOI18N
303  jAllTagsCheckBox.addActionListener(new java.awt.event.ActionListener() {
304  public void actionPerformed(java.awt.event.ActionEvent evt) {
305  jAllTagsCheckBoxActionPerformed(evt);
306  }
307  });
308 
309  javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
310  jPanel1.setLayout(jPanel1Layout);
311  jPanel1Layout.setHorizontalGroup(
312  jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
313  .addGroup(jPanel1Layout.createSequentialGroup()
314  .addContainerGap()
315  .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
316  .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
317  .addGroup(jPanel1Layout.createSequentialGroup()
318  .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
319  .addComponent(descLabel)
320  .addGroup(jPanel1Layout.createSequentialGroup()
321  .addComponent(selectButton, javax.swing.GroupLayout.PREFERRED_SIZE, 96, javax.swing.GroupLayout.PREFERRED_SIZE)
322  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
323  .addComponent(deselectButton))
324  .addComponent(jAllTagsCheckBox))
325  .addGap(0, 0, Short.MAX_VALUE)))
326  .addContainerGap())
327  );
328  jPanel1Layout.setVerticalGroup(
329  jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
330  .addGroup(jPanel1Layout.createSequentialGroup()
331  .addComponent(descLabel)
332  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
333  .addComponent(jAllTagsCheckBox)
334  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
335  .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 168, javax.swing.GroupLayout.PREFERRED_SIZE)
336  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
337  .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
338  .addComponent(selectButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
339  .addComponent(deselectButton)))
340  );
341 
342  javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
343  this.setLayout(layout);
344  layout.setHorizontalGroup(
345  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
346  .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
347  );
348  layout.setVerticalGroup(
349  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
350  .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
351  );
352  }// </editor-fold>//GEN-END:initComponents
353 
354  private void deselectButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deselectButtonActionPerformed
355  selectAllTags(false);
356  }//GEN-LAST:event_deselectButtonActionPerformed
357 
358  private void selectButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_selectButtonActionPerformed
359  selectAllTags(true);
360  }//GEN-LAST:event_selectButtonActionPerformed
361 
362  private void jAllTagsCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jAllTagsCheckBoxActionPerformed
363  selectAllTags(true);
364  }//GEN-LAST:event_jAllTagsCheckBoxActionPerformed
365 
366  private void selectAllTags(boolean select) {
367  Boolean state = Boolean.TRUE;
368  if (!select) {
369  state = Boolean.FALSE;
370  }
371  for (TagName tagName : tagNames) {
372  tagNameSelections.put(tagName.getDisplayName(), state);
373  }
374  updateTagList();
375  tagNamesListBox.repaint();
376  }
377 
378  // Variables declaration - do not modify//GEN-BEGIN:variables
379  private javax.swing.JLabel descLabel;
380  private javax.swing.JButton deselectButton;
381  private javax.swing.JCheckBox jAllTagsCheckBox;
382  private javax.swing.JPanel jPanel1;
383  private javax.swing.JScrollPane jScrollPane1;
384  private javax.swing.JButton selectButton;
385  private javax.swing.JList<String> tagNamesListBox;
386  // End of variables declaration//GEN-END:variables
387 }
Component getListCellRendererComponent(JList<?extends String > list, String value, int index, boolean isSelected, boolean cellHasFocus)

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