Autopsy  4.16.0
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  searchNameRadio.addActionListener((ActionEvent e) -> {
134  searchField.setText("");
135  });
136 
137  searchAccountRadio.addActionListener((ActionEvent e) -> {
138  searchField.setText("");
139  });
140 
141  createAccountBtn.addActionListener(new ActionListener() {
142  @Override
143  public void actionPerformed(ActionEvent e) {
144  new CreatePersonaAccountDialog(detailsPanel);
145  }
146  });
147 
152  addComponentListener(new ComponentAdapter() {
153  @Override
154  public void componentShown(ComponentEvent e) {
155  resetSearchControls();
156  setKeywordSearchEnabled(false, true);
157  }
158  });
159  }
160 
164  class CreateEditCallbackImpl implements PersonaDetailsDialogCallback {
165 
166  @Override
167  public void callback(Persona persona) {
168  if (persona != null) {
169  searchField.setText("");
170  executeSearch();
171  int personaRow = currentResults.indexOf(persona);
172  resultsTable.getSelectionModel().setSelectionInterval(personaRow, personaRow);
173  handleSelectionChange();
174  }
175  createBtn.setEnabled(true);
176  }
177  }
178 
182  private void resetSearchControls() {
183  searchField.setText("");
184  searchNameRadio.setSelected(true);
185  searchAccountRadio.setSelected(false);
186  }
187 
195  private void setKeywordSearchEnabled(boolean selected, boolean setFilterCb) {
196  if (setFilterCb && cbFilterByKeyword.isSelected() != selected) {
197  cbFilterByKeyword.setSelected(selected);
198  }
199 
200  searchField.setEnabled(selected);
201  searchNameRadio.setEnabled(selected);
202  searchAccountRadio.setEnabled(selected);
203 
204  executeSearch();
205  }
206 
207  void setPersona(int index) {
208  Persona persona = currentResults.get(index);
209  selectedPersona = persona;
210  editBtn.setEnabled(true);
211  deleteBtn.setEnabled(true);
212  }
213 
217  final class PersonaFilterTableModel extends DefaultTableModel {
218 
219  private static final long serialVersionUID = 1L;
220 
221  PersonaFilterTableModel(Object[][] rows, String[] colNames) {
222  super(rows, colNames);
223  }
224 
225  @Override
226  public boolean isCellEditable(int row, int column) {
227  return false;
228  }
229  }
230 
231  private void handleSelectionChange(ListSelectionEvent e) {
232  if (e.getValueIsAdjusting()) {
233  return;
234  }
235  handleSelectionChange();
236  }
237 
238  private void handleSelectionChange() {
239  int selectedRow = resultsTable.getSelectedRow();
240  if (selectedRow != -1) {
241  setPersona(resultsTable.getSelectedRow());
242  detailsPanel.setMode(this, PersonaDetailsMode.VIEW, selectedPersona);
243  } else {
244  detailsPanel.clear();
245  }
246  }
247 
248  private void updateResultsTable(Collection<Persona> results) {
249  Object[][] rows = new Object[results.size()][2];
250  int i = 0;
251  for (Persona result : results) {
252  rows[i] = new Object[]{result.getId(), result.getName()};
253  i++;
254  }
255  PersonaFilterTableModel updatedTableModel = new PersonaFilterTableModel(
256  rows,
257  new String[]{"ID", "Name"}
258  );
259 
260  resultsTable.setModel(updatedTableModel);
261  currentResults = new ArrayList<>(results);
262 
263  // Formatting
264  resultsTable.getColumnModel().getColumn(0).setMaxWidth(100);
265  resultsTable.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
266  }
267 
268  @Messages({
269  "PersonasTopComponent_search_exception_Title=There was a failure during the search. Try opening a case to fully initialize the central repository database.",
270  "PersonasTopComponent_search_exception_msg=Failed to search personas.",
271  "PersonasTopComponent_noCR_msg=Central Repository is not enabled.",})
272  private void executeSearch() {
273  // To prevent downstream failures, only execute search if central repository is enabled
274  if (!CentralRepository.isEnabled()) {
275  logger.log(Level.SEVERE, "Central Repository is not enabled, but execute search was called.");
276  JOptionPane.showMessageDialog(this,
277  Bundle.PersonasTopComponent_search_exception_Title(),
278  Bundle.PersonasTopComponent_noCR_msg(),
279  JOptionPane.ERROR_MESSAGE);
280  return;
281  }
282 
283  Collection<Persona> results;
284  try {
285  if (cbFilterByKeyword.isSelected()) {
286  if (searchNameRadio.isSelected()) {
287  results = Persona.getPersonaByName(searchField.getText());
288  } else {
289  results = Persona.getPersonaByAccountIdentifierLike(searchField.getText());
290  }
291  } else {
292  results = Persona.getPersonaByName("");
293  }
294  } catch (CentralRepoException ex) {
295  logger.log(Level.SEVERE, "Failed to search personas", ex);
296  JOptionPane.showMessageDialog(this,
297  Bundle.PersonasTopComponent_search_exception_Title(),
298  Bundle.PersonasTopComponent_search_exception_msg(),
299  JOptionPane.ERROR_MESSAGE);
300  return;
301  }
302 
303  resultsTable.clearSelection();
304  updateResultsTable(results);
305  editBtn.setEnabled(false);
306  deleteBtn.setEnabled(false);
307  }
308 
309  @Override
310  public void componentOpened() {
311  super.componentOpened();
312  WindowManager.getDefault().setTopComponentFloating(this, true);
313  }
314 
320  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
321  private void initComponents() {
322 
323  searchButtonGroup = new javax.swing.ButtonGroup();
324  introTextScrollPane = new javax.swing.JScrollPane();
325  introText = new javax.swing.JTextArea();
326  mainSplitPane = new javax.swing.JSplitPane();
327  searchPanel = new javax.swing.JPanel();
328  searchField = new javax.swing.JTextField();
329  searchNameRadio = new javax.swing.JRadioButton();
330  searchAccountRadio = new javax.swing.JRadioButton();
331  searchBtn = new javax.swing.JButton();
332  resultsPane = new javax.swing.JScrollPane();
333  resultsTable = new javax.swing.JTable();
334  createAccountBtn = new javax.swing.JButton();
335  editBtn = new javax.swing.JButton();
336  deleteBtn = new javax.swing.JButton();
337  createButtonSeparator = new javax.swing.JSeparator();
338  createBtn = new javax.swing.JButton();
339  cbFilterByKeyword = new javax.swing.JCheckBox();
340  detailsScrollPane = new javax.swing.JScrollPane();
342 
343  setName(""); // NOI18N
344 
345  introTextScrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
346 
347  introText.setBackground(getBackground());
348  introText.setColumns(20);
349  introText.setLineWrap(true);
350  introText.setRows(5);
351  introText.setText(org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.introText.text")); // NOI18N
352  introText.setWrapStyleWord(true);
353  introText.setFocusable(false);
354  introTextScrollPane.setViewportView(introText);
355 
356  mainSplitPane.setDividerLocation(400);
357 
358  searchField.setText(org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.searchField.text")); // NOI18N
359 
360  searchButtonGroup.add(searchNameRadio);
361  searchNameRadio.setSelected(true);
362  org.openide.awt.Mnemonics.setLocalizedText(searchNameRadio, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.searchNameRadio.text")); // NOI18N
363 
364  searchButtonGroup.add(searchAccountRadio);
365  org.openide.awt.Mnemonics.setLocalizedText(searchAccountRadio, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.searchAccountRadio.text")); // NOI18N
366 
367  org.openide.awt.Mnemonics.setLocalizedText(searchBtn, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.searchBtn.text")); // NOI18N
368 
369  resultsTable.setToolTipText(org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.resultsTable.toolTipText")); // NOI18N
370  resultsTable.getTableHeader().setReorderingAllowed(false);
371  resultsPane.setViewportView(resultsTable);
372  if (resultsTable.getColumnModel().getColumnCount() > 0) {
373  resultsTable.getColumnModel().getColumn(0).setMaxWidth(25);
374  resultsTable.getColumnModel().getColumn(0).setHeaderValue(org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.resultsTable.columnModel.title0")); // NOI18N
375  resultsTable.getColumnModel().getColumn(1).setHeaderValue(org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.resultsTable.columnModel.title1")); // NOI18N
376  }
377 
378  org.openide.awt.Mnemonics.setLocalizedText(createAccountBtn, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.createAccountBtn.text")); // NOI18N
379 
380  org.openide.awt.Mnemonics.setLocalizedText(editBtn, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.editBtn.text")); // NOI18N
381  editBtn.setEnabled(false);
382 
383  org.openide.awt.Mnemonics.setLocalizedText(deleteBtn, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.deleteBtn.text")); // NOI18N
384  deleteBtn.setEnabled(false);
385 
386  org.openide.awt.Mnemonics.setLocalizedText(createBtn, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.createBtn.text")); // NOI18N
387 
388  org.openide.awt.Mnemonics.setLocalizedText(cbFilterByKeyword, org.openide.util.NbBundle.getMessage(PersonasTopComponent.class, "PersonasTopComponent.cbFilterByKeyword.text")); // NOI18N
389  cbFilterByKeyword.addActionListener(new java.awt.event.ActionListener() {
390  public void actionPerformed(java.awt.event.ActionEvent evt) {
391  cbFilterByKeywordActionPerformed(evt);
392  }
393  });
394 
395  javax.swing.GroupLayout searchPanelLayout = new javax.swing.GroupLayout(searchPanel);
396  searchPanel.setLayout(searchPanelLayout);
397  searchPanelLayout.setHorizontalGroup(
398  searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
399  .addGroup(searchPanelLayout.createSequentialGroup()
400  .addContainerGap()
401  .addGroup(searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
402  .addComponent(createButtonSeparator)
403  .addComponent(resultsPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
404  .addComponent(searchField)
405  .addGroup(searchPanelLayout.createSequentialGroup()
406  .addComponent(searchNameRadio)
407  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
408  .addComponent(searchAccountRadio)
409  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
410  .addComponent(searchBtn))
411  .addGroup(searchPanelLayout.createSequentialGroup()
412  .addGroup(searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
413  .addComponent(createAccountBtn)
414  .addGroup(searchPanelLayout.createSequentialGroup()
415  .addComponent(createBtn)
416  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
417  .addComponent(editBtn)
418  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
419  .addComponent(deleteBtn))
420  .addComponent(cbFilterByKeyword))
421  .addGap(0, 50, Short.MAX_VALUE)))
422  .addContainerGap())
423  );
424  searchPanelLayout.setVerticalGroup(
425  searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
426  .addGroup(searchPanelLayout.createSequentialGroup()
427  .addComponent(cbFilterByKeyword)
428  .addGap(1, 1, 1)
429  .addComponent(searchField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
430  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
431  .addGroup(searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
432  .addComponent(searchNameRadio)
433  .addComponent(searchAccountRadio)
434  .addComponent(searchBtn))
435  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
436  .addComponent(resultsPane, javax.swing.GroupLayout.PREFERRED_SIZE, 302, javax.swing.GroupLayout.PREFERRED_SIZE)
437  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
438  .addGroup(searchPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
439  .addComponent(editBtn)
440  .addComponent(createBtn)
441  .addComponent(deleteBtn))
442  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
443  .addComponent(createButtonSeparator, javax.swing.GroupLayout.PREFERRED_SIZE, 4, javax.swing.GroupLayout.PREFERRED_SIZE)
444  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
445  .addComponent(createAccountBtn, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)
446  .addContainerGap())
447  );
448 
449  mainSplitPane.setLeftComponent(searchPanel);
450 
451  detailsScrollPane.setViewportView(detailsPanel);
452 
453  mainSplitPane.setRightComponent(detailsScrollPane);
454 
455  javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
456  this.setLayout(layout);
457  layout.setHorizontalGroup(
458  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
459  .addComponent(introTextScrollPane)
460  .addComponent(mainSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 724, Short.MAX_VALUE)
461  );
462  layout.setVerticalGroup(
463  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
464  .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
465  .addComponent(introTextScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 49, javax.swing.GroupLayout.PREFERRED_SIZE)
466  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
467  .addComponent(mainSplitPane, javax.swing.GroupLayout.DEFAULT_SIZE, 489, Short.MAX_VALUE))
468  );
469  }// </editor-fold>//GEN-END:initComponents
470 
471  private void cbFilterByKeywordActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbFilterByKeywordActionPerformed
472  setKeywordSearchEnabled(cbFilterByKeyword.isSelected(), false);
473  }//GEN-LAST:event_cbFilterByKeywordActionPerformed
474 
475  // Variables declaration - do not modify//GEN-BEGIN:variables
476  private javax.swing.JCheckBox cbFilterByKeyword;
477  private javax.swing.JButton createAccountBtn;
478  private javax.swing.JButton createBtn;
479  private javax.swing.JSeparator createButtonSeparator;
480  private javax.swing.JButton deleteBtn;
482  private javax.swing.JScrollPane detailsScrollPane;
483  private javax.swing.JButton editBtn;
484  private javax.swing.JTextArea introText;
485  private javax.swing.JScrollPane introTextScrollPane;
486  private javax.swing.JSplitPane mainSplitPane;
487  private javax.swing.JScrollPane resultsPane;
488  private javax.swing.JTable resultsTable;
489  private javax.swing.JRadioButton searchAccountRadio;
490  private javax.swing.JButton searchBtn;
491  private javax.swing.ButtonGroup searchButtonGroup;
492  private javax.swing.JTextField searchField;
493  private javax.swing.JRadioButton searchNameRadio;
494  private javax.swing.JPanel searchPanel;
495  // End of variables declaration//GEN-END:variables
496 
497 }
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-2020 Basis Technology. Generated on: Tue Sep 22 2020
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.