Autopsy  4.12.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;
20 
21 import java.awt.Component;
22 import java.awt.event.MouseAdapter;
23 import java.awt.event.MouseEvent;
24 import java.sql.ResultSet;
25 import java.sql.SQLException;
26 import java.util.ArrayList;
27 import java.util.HashMap;
28 import java.util.LinkedHashMap;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.logging.Level;
32 import javax.swing.JCheckBox;
33 import javax.swing.JLabel;
34 import javax.swing.JList;
35 import javax.swing.JOptionPane;
36 import javax.swing.ListCellRenderer;
37 import javax.swing.ListModel;
38 import javax.swing.event.ListDataListener;
39 import org.openide.util.NbBundle;
43 import org.sleuthkit.datamodel.CaseDbAccessManager;
44 import org.sleuthkit.datamodel.TagName;
45 import org.sleuthkit.datamodel.TskCoreException;
46 
50 @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
51 class PortableCaseTagsListPanel extends javax.swing.JPanel {
52 
53  private List<TagName> tagNames;
54  private final Map<String, Boolean> tagNameSelections = new LinkedHashMap<>();
55  private final TagNamesListModel tagsNamesListModel = new TagNamesListModel();
56  private final TagsNamesListCellRenderer tagsNamesRenderer = new TagsNamesListCellRenderer();
57  private final Map<String, Long> tagCounts = new HashMap<>();
58 
59  private final ReportWizardPortableCaseOptionsPanel wizPanel;
60  private final PortableCaseReportModule.PortableCaseOptions options;
61 
65  PortableCaseTagsListPanel(ReportWizardPortableCaseOptionsPanel wizPanel, PortableCaseReportModule.PortableCaseOptions options) {
66  this.wizPanel = wizPanel;
67  this.options = options;
68  initComponents();
69  customizeComponents();
70  }
71 
72  @NbBundle.Messages({
73  "PortableCaseTagsListPanel.error.errorTitle=Error getting tag names for case",
74  "PortableCaseTagsListPanel.error.noOpenCase=There is no case open",
75  "PortableCaseTagsListPanel.error.errorLoadingTags=Error loading tags",
76  })
77  private void customizeComponents() {
78  // Get the tag names in use for the current case.
79  try {
80  tagNames = Case.getCurrentCaseThrows().getServices().getTagsManager().getTagNamesInUse();
81 
82  // Get the counts for each tag ID
83  String query = "tag_name_id, count(1) AS tag_count " +
84  "FROM (" +
85  "SELECT tag_name_id FROM content_tags UNION ALL SELECT tag_name_id FROM blackboard_artifact_tags" +
86  ") tag_ids GROUP BY tag_name_id"; // NON-NLS
87  GetTagCountsCallback callback = new GetTagCountsCallback();
88  Case.getCurrentCaseThrows().getSleuthkitCase().getCaseDbAccessManager().select(query, callback);
89  Map<Long, Long> tagCountsByID = callback.getTagCountMap();
90 
91  // Mark the tag names as unselected. Note that tagNameSelections is a
92  // LinkedHashMap so that order is preserved and the tagNames and tagNameSelections
93  // containers are "parallel" containers.
94  for (TagName tagName : tagNames) {
95  tagNameSelections.put(tagName.getDisplayName(), Boolean.FALSE);
96  if (tagCountsByID.containsKey(tagName.getId())) {
97  tagCounts.put(tagName.getDisplayName(), tagCountsByID.get(tagName.getId()));
98  } else {
99  tagCounts.put(tagName.getDisplayName(), 0L);
100  }
101  }
102  } catch (TskCoreException ex) {
103  Logger.getLogger(ReportWizardPortableCaseOptionsVisualPanel.class.getName()).log(Level.SEVERE, "Failed to get tag names", ex); // NON-NLS
104  JOptionPane.showMessageDialog(this, Bundle.PortableCaseTagsListPanel_error_errorLoadingTags(), Bundle.PortableCaseTagsListPanel_error_errorTitle(), JOptionPane.ERROR_MESSAGE);
105  return;
106  } catch (NoCurrentCaseException ex) {
107  Logger.getLogger(ReportWizardPortableCaseOptionsVisualPanel.class.getName()).log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS
108  JOptionPane.showMessageDialog(this, Bundle.PortableCaseTagsListPanel_error_noOpenCase(), Bundle.PortableCaseTagsListPanel_error_errorTitle(), JOptionPane.ERROR_MESSAGE);
109  return;
110  }
111 
112  // Set up the tag names JList component to be a collection of check boxes
113  // for selecting tag names. The mouse click listener updates tagNameSelections
114  // to reflect user choices.
115  tagNamesListBox.setModel(tagsNamesListModel);
116  tagNamesListBox.setCellRenderer(tagsNamesRenderer);
117  tagNamesListBox.setVisibleRowCount(-1);
118  tagNamesListBox.addMouseListener(new MouseAdapter() {
119  @Override
120  public void mousePressed(MouseEvent evt) {
121  JList<?> list = (JList) evt.getSource();
122  int index = list.locationToIndex(evt.getPoint());
123  if (index > -1) {
124  String value = tagsNamesListModel.getElementAt(index);
125  tagNameSelections.put(value, !tagNameSelections.get(value));
126  list.repaint();
127  updateTagList();
128  }
129  }
130  });
131  }
132 
136  private void updateTagList() {
137  options.updateTagNames(getSelectedTagNames());
138  wizPanel.setFinish(options.isValid());
139  }
140 
144  private class TagNamesListModel implements ListModel<String> {
145 
146  @Override
147  public int getSize() {
148  return tagNames.size();
149  }
150 
151  @Override
152  public String getElementAt(int index) {
153  return tagNames.get(index).getDisplayName();
154  }
155 
156  @Override
157  public void addListDataListener(ListDataListener l) {
158  // Nothing to do
159  }
160 
161  @Override
162  public void removeListDataListener(ListDataListener l) {
163  // Nothing to do
164  }
165  }
166 
170  private class TagsNamesListCellRenderer extends JCheckBox implements ListCellRenderer<String> {
171  private static final long serialVersionUID = 1L;
172 
173  @Override
174  public Component getListCellRendererComponent(JList<? extends String> list, String value, int index, boolean isSelected, boolean cellHasFocus) {
175  if (value != null) {
176  setEnabled(list.isEnabled());
177  setSelected(tagNameSelections.get(value));
178  setFont(list.getFont());
179  setBackground(list.getBackground());
180  setForeground(list.getForeground());
181  setText(value + " (" + tagCounts.get(value) + ")"); // NON-NLS
182  return this;
183  }
184  return new JLabel();
185  }
186  }
187 
193  private List<TagName> getSelectedTagNames() {
194  List<TagName> selectedTagNames = new ArrayList<>();
195  for (TagName tagName : tagNames) {
196  if (tagNameSelections.get(tagName.getDisplayName())) {
197  selectedTagNames.add(tagName);
198  }
199  }
200  return selectedTagNames;
201  }
202 
206  static class GetTagCountsCallback implements CaseDbAccessManager.CaseDbAccessQueryCallback {
207 
208  private static final Logger logger = Logger.getLogger(GetTagCountsCallback.class.getName());
209  private final Map<Long, Long> tagCounts = new HashMap<>();
210 
211  @Override
212  public void process(ResultSet rs) {
213  try {
214  while (rs.next()) {
215  try {
216  Long tagCount = rs.getLong("tag_count"); // NON-NLS
217  Long tagID = rs.getLong("tag_name_id"); // NON-NLS
218 
219  tagCounts.put(tagID, tagCount);
220 
221  } catch (SQLException ex) {
222  logger.log(Level.WARNING, "Unable to get data_source_obj_id or value from result set", ex); // NON-NLS
223  }
224  }
225  } catch (SQLException ex) {
226  logger.log(Level.WARNING, "Failed to get next result for values by datasource", ex); // NON-NLS
227  }
228  }
229 
235  Map<Long, Long> getTagCountMap() {
236  return tagCounts;
237  }
238  }
239 
245  @SuppressWarnings("unchecked")
246  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
247  private void initComponents() {
248 
249  jPanel1 = new javax.swing.JPanel();
250  jScrollPane1 = new javax.swing.JScrollPane();
251  tagNamesListBox = new javax.swing.JList<>();
252  descLabel = new javax.swing.JLabel();
253  selectButton = new javax.swing.JButton();
254  deselectButton = new javax.swing.JButton();
255 
256  jScrollPane1.setViewportView(tagNamesListBox);
257 
258  org.openide.awt.Mnemonics.setLocalizedText(descLabel, org.openide.util.NbBundle.getMessage(PortableCaseTagsListPanel.class, "PortableCaseTagsListPanel.descLabel.text")); // NOI18N
259 
260  org.openide.awt.Mnemonics.setLocalizedText(selectButton, org.openide.util.NbBundle.getMessage(PortableCaseTagsListPanel.class, "PortableCaseTagsListPanel.selectButton.text")); // NOI18N
261  selectButton.setMaximumSize(new java.awt.Dimension(87, 23));
262  selectButton.setMinimumSize(new java.awt.Dimension(87, 23));
263  selectButton.addActionListener(new java.awt.event.ActionListener() {
264  public void actionPerformed(java.awt.event.ActionEvent evt) {
265  selectButtonActionPerformed(evt);
266  }
267  });
268 
269  org.openide.awt.Mnemonics.setLocalizedText(deselectButton, org.openide.util.NbBundle.getMessage(PortableCaseTagsListPanel.class, "PortableCaseTagsListPanel.deselectButton.text")); // NOI18N
270  deselectButton.addActionListener(new java.awt.event.ActionListener() {
271  public void actionPerformed(java.awt.event.ActionEvent evt) {
272  deselectButtonActionPerformed(evt);
273  }
274  });
275 
276  javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
277  jPanel1.setLayout(jPanel1Layout);
278  jPanel1Layout.setHorizontalGroup(
279  jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
280  .addGroup(jPanel1Layout.createSequentialGroup()
281  .addContainerGap()
282  .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
283  .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 215, Short.MAX_VALUE)
284  .addGroup(jPanel1Layout.createSequentialGroup()
285  .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
286  .addComponent(descLabel)
287  .addGroup(jPanel1Layout.createSequentialGroup()
288  .addComponent(selectButton, javax.swing.GroupLayout.PREFERRED_SIZE, 96, javax.swing.GroupLayout.PREFERRED_SIZE)
289  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
290  .addComponent(deselectButton)))
291  .addGap(0, 0, Short.MAX_VALUE)))
292  .addContainerGap())
293  );
294  jPanel1Layout.setVerticalGroup(
295  jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
296  .addGroup(jPanel1Layout.createSequentialGroup()
297  .addContainerGap()
298  .addComponent(descLabel)
299  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
300  .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 178, Short.MAX_VALUE)
301  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
302  .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
303  .addComponent(selectButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
304  .addComponent(deselectButton)))
305  );
306 
307  javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
308  this.setLayout(layout);
309  layout.setHorizontalGroup(
310  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
311  .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
312  );
313  layout.setVerticalGroup(
314  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
315  .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
316  );
317  }// </editor-fold>//GEN-END:initComponents
318 
319  private void deselectButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deselectButtonActionPerformed
320  for (TagName tagName : tagNames) {
321  tagNameSelections.put(tagName.getDisplayName(), Boolean.FALSE);
322  }
323  updateTagList();
324  tagNamesListBox.repaint();
325  }//GEN-LAST:event_deselectButtonActionPerformed
326 
327  private void selectButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_selectButtonActionPerformed
328  for (TagName tagName : tagNames) {
329  tagNameSelections.put(tagName.getDisplayName(), Boolean.TRUE);
330  }
331  updateTagList();
332  tagNamesListBox.repaint();
333  }//GEN-LAST:event_selectButtonActionPerformed
334 
335 
336  // Variables declaration - do not modify//GEN-BEGIN:variables
337  private javax.swing.JLabel descLabel;
338  private javax.swing.JButton deselectButton;
339  private javax.swing.JPanel jPanel1;
340  private javax.swing.JScrollPane jScrollPane1;
341  private javax.swing.JButton selectButton;
342  private javax.swing.JList<String> tagNamesListBox;
343  // End of variables declaration//GEN-END:variables
344 }
Component getListCellRendererComponent(JList<?extends String > list, String value, int index, boolean isSelected, boolean cellHasFocus)

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