Autopsy  4.19.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
PersonasTopComponent.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2020 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.centralrepository.persona;
20 
21 import java.awt.event.ActionEvent;
22 import java.awt.event.ActionListener;
23 import java.awt.event.ComponentAdapter;
24 import java.awt.event.ComponentEvent;
25 import java.util.ArrayList;
26 import java.util.Collection;
27 import java.util.List;
28 import java.util.logging.Level;
29 import javax.swing.JOptionPane;
30 import javax.swing.JTable;
31 import javax.swing.ListSelectionModel;
32 import javax.swing.event.AncestorListener;
33 import javax.swing.event.AncestorEvent;
34 import javax.swing.event.ListSelectionEvent;
35 import javax.swing.event.ListSelectionListener;
36 import javax.swing.table.DefaultTableModel;
37 import org.openide.DialogDisplayer;
38 import org.openide.NotifyDescriptor;
39 import org.openide.util.NbBundle.Messages;
40 import org.openide.windows.RetainLocation;
41 import org.openide.windows.TopComponent;
42 import org.openide.windows.WindowManager;
47 
52 @TopComponent.Description(preferredID = "PersonasTopComponent", persistenceType = TopComponent.PERSISTENCE_NEVER)
53 @TopComponent.Registration(mode = "personas", openAtStartup = false)
54 @RetainLocation("personas")
55 @SuppressWarnings("PMD.SingularField")
56 public final class PersonasTopComponent extends TopComponent {
57 
58  private static final long serialVersionUID = 1L;
59 
60  private static final Logger logger = Logger.getLogger(PersonasTopComponent.class.getName());
61 
62  private List<Persona> currentResults = null;
63  private Persona selectedPersona = null;
64 
65  @Messages({
66  "PersonasTopComponent_Name=Personas",
67  "PersonasTopComponent_delete_exception_Title=Delete failure",
68  "PersonasTopComponent_delete_exception_msg=Failed to delete persona.",
69  "PersonasTopComponent_delete_confirmation_Title=Are you sure?",
70  "PersonasTopComponent_delete_confirmation_msg=Are you sure you want to delete this persona?",})
72  initComponents();
73  setName(Bundle.PersonasTopComponent_Name());
74 
75  searchBtn.addActionListener(new ActionListener() {
76  @Override
77  public void actionPerformed(ActionEvent e) {
78  executeSearch();
79  }
80  });
81 
82  editBtn.addActionListener(new ActionListener() {
83  @Override
84  public void actionPerformed(ActionEvent e) {
86  PersonaDetailsMode.EDIT, selectedPersona, new CreateEditCallbackImpl());
87  }
88  });
89 
90  createBtn.addActionListener(new ActionListener() {
91  @Override
92  public void actionPerformed(ActionEvent e) {
94  PersonaDetailsMode.CREATE, selectedPersona, new CreateEditCallbackImpl());
95  }
96  });
97 
98  deleteBtn.addActionListener(new ActionListener() {
99  @Override
100  public void actionPerformed(ActionEvent e) {
101  NotifyDescriptor confirm = new NotifyDescriptor.Confirmation(
102  Bundle.PersonasTopComponent_delete_confirmation_msg(),
103  Bundle.PersonasTopComponent_delete_confirmation_Title(),
104  NotifyDescriptor.YES_NO_OPTION);
105  DialogDisplayer.getDefault().notify(confirm);
106  if (confirm.getValue().equals(NotifyDescriptor.YES_OPTION)) {
107  try {
108  if (selectedPersona != null) {
109  selectedPersona.delete();
110  }
111  } catch (CentralRepoException ex) {
112  logger.log(Level.SEVERE, "Failed to delete persona: " + selectedPersona.getName(), ex);
113  JOptionPane.showMessageDialog(PersonasTopComponent.this,
114  Bundle.PersonasTopComponent_delete_exception_msg(),
115  Bundle.PersonasTopComponent_delete_exception_Title(),
116  JOptionPane.ERROR_MESSAGE);
117  return;
118  }
119  executeSearch();
120  }
121  }
122  });
123 
124  // Results table
125  resultsTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
126  resultsTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
127  @Override
128  public void valueChanged(ListSelectionEvent e) {
129  handleSelectionChange(e);
130  }
131  });
132 
133  createAccountBtn.addActionListener(new ActionListener() {
134  @Override
135  public void actionPerformed(ActionEvent e) {
136  new CreatePersonaAccountDialog(detailsPanel);
137  }
138  });
139 
144  addComponentListener(new ComponentAdapter() {
145  @Override
146  public void componentShown(ComponentEvent e) {
147  resetSearchControls();
148  setKeywordSearchEnabled(false, true);
149  }
150  });
151  }
152 
156  class CreateEditCallbackImpl implements PersonaDetailsDialogCallback {
157 
158  @Override
159  public void callback(Persona persona) {
160  if (persona != null) {
161  searchField.setText("");
162  executeSearch();
163  int personaRow = currentResults.indexOf(persona);
164  resultsTable.getSelectionModel().setSelectionInterval(personaRow, personaRow);
165  handleSelectionChange();
166  }
167  createBtn.setEnabled(true);
168  }
169  }
170 
174  private void resetSearchControls() {
175  searchField.setText("");
176  searchNameRadio.setSelected(true);
177  searchAccountRadio.setSelected(false);
178  }
179 
187  private void setKeywordSearchEnabled(boolean selected, boolean setFilterCb) {
188  if (setFilterCb && cbFilterByKeyword.isSelected() != selected) {
189  cbFilterByKeyword.setSelected(selected);
190  }
191 
192  searchField.setEnabled(selected);
193  searchNameRadio.setEnabled(selected);
194  searchAccountRadio.setEnabled(selected);
195 
196  executeSearch();
197  }
198 
199  void setPersona(int index) {
200  Persona persona = currentResults.get(index);
201  selectedPersona = persona;
202  editBtn.setEnabled(true);
203  deleteBtn.setEnabled(true);
204  }
205 
209  final class PersonaFilterTableModel extends DefaultTableModel {
210 
211  private static final long serialVersionUID = 1L;
212 
213  PersonaFilterTableModel(Object[][] rows, String[] colNames) {
214  super(rows, colNames);
215  }
216 
217  @Override
218  public boolean isCellEditable(int row, int column) {
219  return false;
220  }
221  }
222 
223  private void handleSelectionChange(ListSelectionEvent e) {
224  if (e.getValueIsAdjusting()) {
225  return;
226  }
227  handleSelectionChange();
228  }
229 
230  private void handleSelectionChange() {
231  int selectedRow = resultsTable.getSelectedRow();
232  if (selectedRow != -1) {
233  setPersona(resultsTable.getSelectedRow());
234  detailsPanel.setMode(this, PersonaDetailsMode.VIEW, selectedPersona);
235  } else {
236  detailsPanel.clear();
237  }
238  }
239 
240  private void updateResultsTable(Collection<Persona> results) {
241  Object[][] rows = new Object[results.size()][2];
242  int i = 0;
243  for (Persona result : results) {
244  rows[i] = new Object[]{result.getId(), result.getName()};
245  i++;
246  }
247  PersonaFilterTableModel updatedTableModel = new PersonaFilterTableModel(
248  rows,
249  new String[]{"ID", "Name"}
250  );
251 
252  resultsTable.setModel(updatedTableModel);
253  currentResults = new ArrayList<>(results);
254 
255  // Formatting
256  resultsTable.getColumnModel().getColumn(0).setMaxWidth(100);
257  resultsTable.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
258  }
259 
260  @Messages({
261  "PersonasTopComponent_search_exception_Title=There was a failure during the search. Try opening a case to fully initialize the central repository database.",
262  "PersonasTopComponent_search_exception_msg=Failed to search personas.",
263  "PersonasTopComponent_noCR_msg=Central Repository is not enabled.",})
264  private void executeSearch() {
265  // To prevent downstream failures, only execute search if central repository is enabled
266  if (!CentralRepository.isEnabled()) {
267  logger.log(Level.SEVERE, "Central Repository is not enabled, but execute search was called.");
268  JOptionPane.showMessageDialog(this,
269  Bundle.PersonasTopComponent_search_exception_Title(),
270  Bundle.PersonasTopComponent_noCR_msg(),
271  JOptionPane.ERROR_MESSAGE);
272  return;
273  }
274 
275  Collection<Persona> results;
276  try {
277  if (cbFilterByKeyword.isSelected()) {
278  if (searchNameRadio.isSelected()) {
279  results = Persona.getPersonaByName(searchField.getText());
280  } else {
281  results = Persona.getPersonaByAccountIdentifierLike(searchField.getText());
282  }
283  } else {
284  results = Persona.getPersonaByName("");
285  }
286  } catch (CentralRepoException ex) {
287  logger.log(Level.SEVERE, "Failed to search personas", ex);
288  JOptionPane.showMessageDialog(this,
289  Bundle.PersonasTopComponent_search_exception_Title(),
290  Bundle.PersonasTopComponent_search_exception_msg(),
291  JOptionPane.ERROR_MESSAGE);
292  return;
293  }
294 
295  resultsTable.clearSelection();
296  updateResultsTable(results);
297  editBtn.setEnabled(false);
298  deleteBtn.setEnabled(false);
299  }
300 
301  @Override
302  public void componentOpened() {
303  super.componentOpened();
304  WindowManager.getDefault().setTopComponentFloating(this, true);
305  }
306 
312  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
313  private void initComponents() {
314 
315  searchButtonGroup = new javax.swing.ButtonGroup();
316  introTextScrollPane = new javax.swing.JScrollPane();
317  introText = new javax.swing.JTextArea();
318  mainSplitPane = new javax.swing.JSplitPane();
319  searchPanel = new javax.swing.JPanel();
320  searchField = new javax.swing.JTextField();
321  searchNameRadio = new javax.swing.JRadioButton();
322  searchAccountRadio = new javax.swing.JRadioButton();
323  searchBtn = new javax.swing.JButton();
324  resultsPane = new javax.swing.JScrollPane();
325  resultsTable = new javax.swing.JTable();
326  createAccountBtn = new javax.swing.JButton();
327  editBtn = new javax.swing.JButton();
328  deleteBtn = new javax.swing.JButton();
329  createButtonSeparator = new javax.swing.JSeparator();
330  createBtn = new javax.swing.JButton();
331  cbFilterByKeyword = new javax.swing.JCheckBox();
332  detailsScrollPane = new javax.swing.JScrollPane();
334 
335  setName(""); // NOI18N
336 
337  introTextScrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
338 
339  introText.setBackground(getBackground());
340  introText.setColumns(20);
341  introText.setLineWrap(true);
342  introText.setRows(5);
343  introText.setText(org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.introText.text")); // NOI18N
344  introText.setWrapStyleWord(true);
345  introText.setFocusable(false);
346  introTextScrollPane.setViewportView(introText);
347 
348  mainSplitPane.setDividerLocation(400);
349 
350  searchField.setText(org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.searchField.text")); // NOI18N
351 
352  searchButtonGroup.add(searchNameRadio);
353  searchNameRadio.setSelected(true);
354  org.openide.awt.Mnemonics.setLocalizedText(searchNameRadio, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.searchNameRadio.text")); // NOI18N
355 
356  searchButtonGroup.add(searchAccountRadio);
357  org.openide.awt.Mnemonics.setLocalizedText(searchAccountRadio, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.searchAccountRadio.text")); // NOI18N
358 
359  org.openide.awt.Mnemonics.setLocalizedText(searchBtn, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.searchBtn.text")); // NOI18N
360 
361  resultsTable.setToolTipText(org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.resultsTable.toolTipText")); // NOI18N
362  resultsTable.getTableHeader().setReorderingAllowed(false);
363  resultsPane.setViewportView(resultsTable);
364  if (resultsTable.getColumnModel().getColumnCount() > 0) {
365  resultsTable.getColumnModel().getColumn(0).setMaxWidth(25);
366  resultsTable.getColumnModel().getColumn(0).setHeaderValue(org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.resultsTable.columnModel.title0")); // NOI18N
367  resultsTable.getColumnModel().getColumn(1).setHeaderValue(org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.resultsTable.columnModel.title1")); // NOI18N
368  }
369 
370  org.openide.awt.Mnemonics.setLocalizedText(createAccountBtn, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.createAccountBtn.text")); // NOI18N
371 
372  org.openide.awt.Mnemonics.setLocalizedText(editBtn, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.editBtn.text")); // NOI18N
373  editBtn.setEnabled(false);
374 
375  org.openide.awt.Mnemonics.setLocalizedText(deleteBtn, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.deleteBtn.text")); // NOI18N
376  deleteBtn.setEnabled(false);
377 
378  org.openide.awt.Mnemonics.setLocalizedText(createBtn, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.createBtn.text")); // NOI18N
379 
380  org.openide.awt.Mnemonics.setLocalizedText(cbFilterByKeyword, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.cbFilterByKeyword.text")); // NOI18N
381  cbFilterByKeyword.addActionListener(new java.awt.event.ActionListener() {
382  public void actionPerformed(java.awt.event.ActionEvent evt) {
383  cbFilterByKeywordActionPerformed(evt);
384  }
385  });
386 
387  javax.swing.GroupLayout searchPanelLayout = new javax.swing.GroupLayout(searchPanel);
388  searchPanel.setLayout(searchPanelLayout);
389  searchPanelLayout.setHorizontalGroup(
390  searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
391  .addGroup(searchPanelLayout.createSequentialGroup()
392  .addContainerGap()
393  .addGroup(searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
394  .addComponent(createButtonSeparator)
395  .addComponent(resultsPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
396  .addComponent(searchField)
397  .addGroup(searchPanelLayout.createSequentialGroup()
398  .addComponent(searchNameRadio)
399  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
400  .addComponent(searchAccountRadio)
401  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
402  .addComponent(searchBtn))
403  .addGroup(searchPanelLayout.createSequentialGroup()
404  .addGroup(searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
405  .addComponent(createAccountBtn)
406  .addGroup(searchPanelLayout.createSequentialGroup()
407  .addComponent(createBtn)
408  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
409  .addComponent(editBtn)
410  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
411  .addComponent(deleteBtn))
412  .addComponent(cbFilterByKeyword))
413  .addGap(0, 50, Short.MAX_VALUE)))
414  .addContainerGap())
415  );
416  searchPanelLayout.setVerticalGroup(
417  searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
418  .addGroup(searchPanelLayout.createSequentialGroup()
419  .addComponent(cbFilterByKeyword)
420  .addGap(1, 1, 1)
421  .addComponent(searchField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
422  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
423  .addGroup(searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
424  .addComponent(searchNameRadio)
425  .addComponent(searchAccountRadio)
426  .addComponent(searchBtn))
427  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
428  .addComponent(resultsPane, javax.swing.GroupLayout.PREFERRED_SIZE, 302, javax.swing.GroupLayout.PREFERRED_SIZE)
429  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
430  .addGroup(searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
431  .addComponent(editBtn)
432  .addComponent(createBtn)
433  .addComponent(deleteBtn))
434  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
435  .addComponent(createButtonSeparator, javax.swing.GroupLayout.PREFERRED_SIZE, 4, javax.swing.GroupLayout.PREFERRED_SIZE)
436  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
437  .addComponent(createAccountBtn, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)
438  .addContainerGap())
439  );
440 
441  mainSplitPane.setLeftComponent(searchPanel);
442 
443  detailsScrollPane.setViewportView(detailsPanel);
444 
445  mainSplitPane.setRightComponent(detailsScrollPane);
446 
447  javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
448  this.setLayout(layout);
449  layout.setHorizontalGroup(
450  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
451  .addComponent(introTextScrollPane)
452  .addComponent(mainSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 724, Short.MAX_VALUE)
453  );
454  layout.setVerticalGroup(
455  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
456  .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
457  .addComponent(introTextScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 49, javax.swing.GroupLayout.PREFERRED_SIZE)
458  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
459  .addComponent(mainSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 489, Short.MAX_VALUE))
460  );
461  }// </editor-fold>//GEN-END:initComponents
462 
463  private void cbFilterByKeywordActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbFilterByKeywordActionPerformed
464  setKeywordSearchEnabled(cbFilterByKeyword.isSelected(), false);
465  }//GEN-LAST:event_cbFilterByKeywordActionPerformed
466 
467  // Variables declaration - do not modify//GEN-BEGIN:variables
468  private javax.swing.JCheckBox cbFilterByKeyword;
469  private javax.swing.JButton createAccountBtn;
470  private javax.swing.JButton createBtn;
471  private javax.swing.JSeparator createButtonSeparator;
472  private javax.swing.JButton deleteBtn;
474  private javax.swing.JScrollPane detailsScrollPane;
475  private javax.swing.JButton editBtn;
476  private javax.swing.JTextArea introText;
477  private javax.swing.JScrollPane introTextScrollPane;
478  private javax.swing.JSplitPane mainSplitPane;
479  private javax.swing.JScrollPane resultsPane;
480  private javax.swing.JTable resultsTable;
481  private javax.swing.JRadioButton searchAccountRadio;
482  private javax.swing.JButton searchBtn;
483  private javax.swing.ButtonGroup searchButtonGroup;
484  private javax.swing.JTextField searchField;
485  private javax.swing.JRadioButton searchNameRadio;
486  private javax.swing.JPanel searchPanel;
487  // End of variables declaration//GEN-END:variables
488 
489 }
static Collection< Persona > getPersonaByName(String partialName)
Definition: Persona.java:438
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
org.sleuthkit.autopsy.centralrepository.persona.PersonaDetailsPanel detailsPanel
static Collection< Persona > getPersonaByAccountIdentifierLike(String partialName)
Definition: Persona.java:489

Copyright © 2012-2021 Basis Technology. Generated on: Thu Sep 30 2021
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.