Autopsy  4.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
GlobalEditListPanel.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2011-2017 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.keywordsearch;
20 
21 import java.awt.EventQueue;
22 import java.beans.PropertyChangeEvent;
23 import java.beans.PropertyChangeListener;
24 import java.util.Arrays;
25 import java.util.List;
26 import java.util.logging.Level;
27 import java.util.regex.Pattern;
28 import java.util.regex.PatternSyntaxException;
29 import javax.swing.JTable;
30 import javax.swing.ListSelectionModel;
31 import javax.swing.event.ListSelectionEvent;
32 import javax.swing.event.ListSelectionListener;
33 import javax.swing.table.AbstractTableModel;
34 import javax.swing.table.TableColumn;
35 import org.netbeans.spi.options.OptionsPanelController;
36 import org.openide.util.NbBundle;
40 
44 class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionListener, OptionsPanel {
45 
46  private static final Logger logger = Logger.getLogger(GlobalEditListPanel.class.getName());
47  private static final long serialVersionUID = 1L;
48  private final KeywordTableModel tableModel;
49  private KeywordList currentKeywordList;
50 
54  GlobalEditListPanel() {
55  tableModel = new KeywordTableModel();
56  initComponents();
57  customizeComponents();
58  }
59 
60  private void customizeComponents() {
61  newKeywordsButton.setToolTipText((NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.customizeComponents.addWordToolTip")));
62  deleteWordButton.setToolTipText(NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.customizeComponents.removeSelectedMsg"));
63 
64  keywordTable.getParent().setBackground(keywordTable.getBackground());
65  final int width = jScrollPane1.getPreferredSize().width;
66  keywordTable.setAutoResizeMode(JTable.AUTO_RESIZE_NEXT_COLUMN);
67  TableColumn column;
68  for (int i = 0; i < keywordTable.getColumnCount(); i++) {
69  column = keywordTable.getColumnModel().getColumn(i);
70  if (i == 0) {
71  column.setPreferredWidth(((int) (width * 0.90)));
72  } else {
73  column.setPreferredWidth(((int) (width * 0.10)));
74  }
75  }
76  keywordTable.setCellSelectionEnabled(false);
77  keywordTable.setRowSelectionAllowed(true);
78 
79  final ListSelectionModel lsm = keywordTable.getSelectionModel();
80  lsm.addListSelectionListener(new ListSelectionListener() {
81  @Override
82  public void valueChanged(ListSelectionEvent e) {
83  boolean canDelete = !(lsm.isSelectionEmpty() || currentKeywordList.isEditable() || IngestManager.getInstance().isIngestRunning());
84  boolean canEdit = canDelete && (lsm.getMaxSelectionIndex() == lsm.getMinSelectionIndex()); //edit only enabled with single selection
85  deleteWordButton.setEnabled(canDelete);
86  editWordButton.setEnabled(canEdit);
87  }
88  });
89 
90  setButtonStates();
91 
92  IngestManager.getInstance().addIngestJobEventListener(new PropertyChangeListener() {
93  @Override
94  public void propertyChange(PropertyChangeEvent evt) {
95  Object source = evt.getSource();
96  if (source instanceof String && ((String) source).equals("LOCAL")) { //NON-NLS
97  EventQueue.invokeLater(() -> {
98  setButtonStates();
99  });
100  }
101  }
102  });
103  }
104 
108  void setButtonStates() {
109  boolean isIngestRunning = IngestManager.getInstance().isIngestRunning();
110  boolean isListSelected = currentKeywordList != null;
111 
112  // items that only need a selected list
113  boolean canEditList = isListSelected && !isIngestRunning;
114  ingestMessagesCheckbox.setEnabled(canEditList);
115  ingestMessagesCheckbox.setSelected(currentKeywordList != null && currentKeywordList.getIngestMessages());
116 
117  // items that need an unlocked list w/out ingest running
118  boolean canAddWord = canEditList && !currentKeywordList.isEditable();
119  newKeywordsButton.setEnabled(canAddWord);
120 
121  // items that need a non-empty list
122  if ((currentKeywordList == null) || (currentKeywordList.getKeywords().isEmpty())) {
123  deleteWordButton.setEnabled(false);
124  editWordButton.setEnabled(false);
125  }
126  }
127 
128  @NbBundle.Messages("GlobalEditListPanel.editKeyword.title=Edit Keyword")
135  private boolean addKeywordsAction(String existingKeywords, boolean isLiteral, boolean isWholeWord) {
136  String keywordsToRedisplay = existingKeywords;
137  AddKeywordsDialog dialog = new AddKeywordsDialog();
138 
139  int goodCount = 0;
140  int dupeCount = 0;
141  int badCount = 1; // Default to 1 so we enter the loop the first time
142 
143  if (!existingKeywords.isEmpty()){ //if there is an existing keyword then this action was called by the edit button
144  dialog.setTitle(NbBundle.getMessage(GlobalEditListPanel.class, "GlobalEditListPanel.editKeyword.title"));
145  }
146  while (badCount > 0) {
147  dialog.setInitialKeywordList(keywordsToRedisplay, isLiteral, isWholeWord);
148  dialog.display();
149 
150  goodCount = 0;
151  dupeCount = 0;
152  badCount = 0;
153  keywordsToRedisplay = "";
154 
155  if (!dialog.getKeywords().isEmpty()) {
156 
157  for (String newWord : dialog.getKeywords()) {
158  if (newWord.isEmpty()) {
159  continue;
160  }
161 
162  final Keyword keyword = new Keyword(newWord, !dialog.isKeywordRegex(), dialog.isKeywordExact(), currentKeywordList.getName(), newWord);
163  if (currentKeywordList.hasKeyword(keyword)) {
164  dupeCount++;
165  continue;
166  }
167 
168  //check if valid
169  boolean valid = true;
170  try {
171  Pattern.compile(newWord);
172  } catch (PatternSyntaxException ex1) {
173  valid = false;
174  } catch (IllegalArgumentException ex2) {
175  valid = false;
176  }
177  if (!valid) {
178 
179  // Invalid keywords will reappear in the UI
180  keywordsToRedisplay += newWord + "\n";
181  badCount++;
182  continue;
183  }
184 
185  // Add the new keyword
186  tableModel.addKeyword(keyword);
187  goodCount++;
188  }
189  XmlKeywordSearchList.getCurrent().addList(currentKeywordList);
190  firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
191 
192  if ((badCount > 0) || (dupeCount > 0)) {
193  // Display the error counts to the user
194  // The add keywords dialog will pop up again if any were invalid with any
195  // invalid entries (valid entries and dupes will disappear)
196 
197  String summary = "";
198  KeywordSearchUtil.DIALOG_MESSAGE_TYPE level = KeywordSearchUtil.DIALOG_MESSAGE_TYPE.INFO;
199  if (goodCount > 0) {
200  if (goodCount > 1) {
201  summary += NbBundle.getMessage(GlobalEditListPanel.class, "GlobalEditListPanel.keywordsAddedPlural.text", goodCount) + "\n";
202  } else {
203  summary += NbBundle.getMessage(GlobalEditListPanel.class, "GlobalEditListPanel.keywordsAdded.text", goodCount) + "\n";
204  }
205  }
206  if (dupeCount > 0) {
207  if (dupeCount > 1) {
208  summary += NbBundle.getMessage(GlobalEditListPanel.class, "GlobalEditListPanel.keywordDupesSkippedPlural.text", dupeCount) + "\n";
209  } else {
210  summary += NbBundle.getMessage(GlobalEditListPanel.class, "GlobalEditListPanel.keywordDupesSkipped.text", dupeCount) + "\n";
211  }
212  level = KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN;
213  }
214  if (badCount > 0) {
215  if (badCount > 1) {
216  summary += NbBundle.getMessage(GlobalEditListPanel.class, "GlobalEditListPanel.keywordErrorsPlural.text", badCount) + "\n";
217  } else {
218  summary += NbBundle.getMessage(GlobalEditListPanel.class, "GlobalEditListPanel.keywordErrors.text", badCount) + "\n";
219  }
220  level = KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR;
221  }
222  KeywordSearchUtil.displayDialog(NbBundle.getMessage(this.getClass(), "GlobalEditListPanel.addKeywordResults.text"),
223  summary, level);
224  }
225  }
226  }
227  setFocusOnKeywordTextBox();
228  setButtonStates();
229  return (goodCount >= 1 && dupeCount == 0);
230  }
231 
237  private void deleteKeywordAction(int[] selectedKeywords) {
238  tableModel.deleteSelected(selectedKeywords);
239  XmlKeywordSearchList.getCurrent().addList(currentKeywordList);
240  setButtonStates();
241  }
242 
248  @SuppressWarnings("unchecked")
249  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
250  private void initComponents() {
251 
252  listEditorPanel = new javax.swing.JPanel();
253  jScrollPane1 = new javax.swing.JScrollPane();
254  keywordTable = new javax.swing.JTable();
255  ingestMessagesCheckbox = new javax.swing.JCheckBox();
256  keywordsLabel = new javax.swing.JLabel();
257  newKeywordsButton = new javax.swing.JButton();
258  deleteWordButton = new javax.swing.JButton();
259  editWordButton = new javax.swing.JButton();
260 
261  setMinimumSize(new java.awt.Dimension(0, 0));
262 
263  listEditorPanel.setMinimumSize(new java.awt.Dimension(0, 0));
264 
265  jScrollPane1.setPreferredSize(new java.awt.Dimension(340, 300));
266 
267  keywordTable.setModel(tableModel);
268  keywordTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_OFF);
269  keywordTable.setGridColor(new java.awt.Color(153, 153, 153));
270  keywordTable.setMaximumSize(new java.awt.Dimension(30000, 30000));
271  keywordTable.getTableHeader().setReorderingAllowed(false);
272  jScrollPane1.setViewportView(keywordTable);
273 
274  ingestMessagesCheckbox.setSelected(true);
275  ingestMessagesCheckbox.setText(org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class, "KeywordSearchEditListPanel.ingestMessagesCheckbox.text")); // NOI18N
276  ingestMessagesCheckbox.setToolTipText(org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class, "KeywordSearchEditListPanel.ingestMessagesCheckbox.toolTipText")); // NOI18N
277  ingestMessagesCheckbox.addActionListener(new java.awt.event.ActionListener() {
278  public void actionPerformed(java.awt.event.ActionEvent evt) {
279  ingestMessagesCheckboxActionPerformed(evt);
280  }
281  });
282 
283  keywordsLabel.setText(org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class, "KeywordSearchEditListPanel.keywordsLabel.text")); // NOI18N
284 
285  newKeywordsButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/add16.png"))); // NOI18N
286  newKeywordsButton.setText(org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class, "GlobalEditListPanel.newKeywordsButton.text")); // NOI18N
287  newKeywordsButton.addActionListener(new java.awt.event.ActionListener() {
288  public void actionPerformed(java.awt.event.ActionEvent evt) {
289  newKeywordsButtonActionPerformed(evt);
290  }
291  });
292 
293  deleteWordButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/delete16.png"))); // NOI18N
294  deleteWordButton.setText(org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class, "KeywordSearchEditListPanel.deleteWordButton.text")); // NOI18N
295  deleteWordButton.addActionListener(new java.awt.event.ActionListener() {
296  public void actionPerformed(java.awt.event.ActionEvent evt) {
297  deleteWordButtonActionPerformed(evt);
298  }
299  });
300 
301  editWordButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/edit16.png"))); // NOI18N
302  editWordButton.setText(org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class, "GlobalEditListPanel.editWordButton.text")); // NOI18N
303  editWordButton.addActionListener(new java.awt.event.ActionListener() {
304  public void actionPerformed(java.awt.event.ActionEvent evt) {
305  editWordButtonActionPerformed(evt);
306  }
307  });
308 
309  javax.swing.GroupLayout listEditorPanelLayout = new javax.swing.GroupLayout(listEditorPanel);
310  listEditorPanel.setLayout(listEditorPanelLayout);
311  listEditorPanelLayout.setHorizontalGroup(
312  listEditorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
313  .addGroup(listEditorPanelLayout.createSequentialGroup()
314  .addContainerGap()
315  .addGroup(listEditorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
316  .addGroup(listEditorPanelLayout.createSequentialGroup()
317  .addComponent(keywordsLabel)
318  .addGap(0, 0, Short.MAX_VALUE))
319  .addGroup(listEditorPanelLayout.createSequentialGroup()
320  .addGap(10, 10, 10)
321  .addGroup(listEditorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
322  .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 483, Short.MAX_VALUE)
323  .addGroup(listEditorPanelLayout.createSequentialGroup()
324  .addGroup(listEditorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
325  .addComponent(ingestMessagesCheckbox)
326  .addGroup(listEditorPanelLayout.createSequentialGroup()
327  .addComponent(newKeywordsButton, javax.swing.GroupLayout.PREFERRED_SIZE, 133, javax.swing.GroupLayout.PREFERRED_SIZE)
328  .addGap(14, 14, 14)
329  .addComponent(editWordButton, javax.swing.GroupLayout.PREFERRED_SIZE, 132, javax.swing.GroupLayout.PREFERRED_SIZE)
330  .addGap(14, 14, 14)
331  .addComponent(deleteWordButton, javax.swing.GroupLayout.PREFERRED_SIZE, 144, javax.swing.GroupLayout.PREFERRED_SIZE)))
332  .addGap(0, 0, Short.MAX_VALUE)))))
333  .addContainerGap())
334  );
335 
336  listEditorPanelLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {deleteWordButton, editWordButton, newKeywordsButton});
337 
338  listEditorPanelLayout.setVerticalGroup(
339  listEditorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
340  .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, listEditorPanelLayout.createSequentialGroup()
341  .addContainerGap()
342  .addComponent(keywordsLabel)
343  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
344  .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 257, Short.MAX_VALUE)
345  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
346  .addGroup(listEditorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
347  .addComponent(deleteWordButton)
348  .addComponent(newKeywordsButton)
349  .addComponent(editWordButton))
350  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
351  .addComponent(ingestMessagesCheckbox)
352  .addGap(9, 9, 9))
353  );
354 
355  javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
356  this.setLayout(layout);
357  layout.setHorizontalGroup(
358  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
359  .addComponent(listEditorPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
360  );
361  layout.setVerticalGroup(
362  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
363  .addGroup(layout.createSequentialGroup()
364  .addComponent(listEditorPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
365  .addGap(5, 5, 5))
366  );
367  }// </editor-fold>//GEN-END:initComponents
368 
369  private void deleteWordButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteWordButtonActionPerformed
370  if (KeywordSearchUtil.displayConfirmDialog(NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.removeKwMsg"),
371  NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.deleteWordButtonActionPerformed.delConfirmMsg"),
372  KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN)) {
373  deleteKeywordAction(keywordTable.getSelectedRows());
374  firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
375  }
376  }//GEN-LAST:event_deleteWordButtonActionPerformed
377 
378  private void ingestMessagesCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_ingestMessagesCheckboxActionPerformed
379  currentKeywordList.setIngestMessages(ingestMessagesCheckbox.isSelected());
380  XmlKeywordSearchList updater = XmlKeywordSearchList.getCurrent();
381  updater.addList(currentKeywordList);
382  firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
383  }//GEN-LAST:event_ingestMessagesCheckboxActionPerformed
384 
385  private void newKeywordsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newKeywordsButtonActionPerformed
386  addKeywordsAction("", true, true);
387  }//GEN-LAST:event_newKeywordsButtonActionPerformed
388 
389  private void editWordButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_editWordButtonActionPerformed
390  int[] selectedKeywords = keywordTable.getSelectedRows();
391  if (selectedKeywords.length == 1) {
392  Keyword currentKeyword = currentKeywordList.getKeywords().get(selectedKeywords[0]);
393  if (addKeywordsAction(currentKeyword.getSearchTerm(), currentKeyword.searchTermIsLiteral(), currentKeyword.searchTermIsWholeWord())) {
394  deleteKeywordAction(selectedKeywords);
395  }
396  }
397  }//GEN-LAST:event_editWordButtonActionPerformed
398 
399  // Variables declaration - do not modify//GEN-BEGIN:variables
400  private javax.swing.JButton deleteWordButton;
401  private javax.swing.JButton editWordButton;
402  private javax.swing.JCheckBox ingestMessagesCheckbox;
403  private javax.swing.JScrollPane jScrollPane1;
404  private javax.swing.JTable keywordTable;
405  private javax.swing.JLabel keywordsLabel;
406  private javax.swing.JPanel listEditorPanel;
407  private javax.swing.JButton newKeywordsButton;
408  // End of variables declaration//GEN-END:variables
409 
410  @Override
411  public void valueChanged(ListSelectionEvent e) {
412  //respond to list selection changes in KeywordSearchListManagementPanel
413  ListSelectionModel listSelectionModel = (ListSelectionModel) e.getSource();
414  if (!listSelectionModel.isSelectionEmpty()) {
415  int index = listSelectionModel.getMinSelectionIndex();
416 
417  listSelectionModel.setSelectionInterval(index, index);
418  XmlKeywordSearchList loader = XmlKeywordSearchList.getCurrent();
419 
420  currentKeywordList = loader.getListsL(false).get(index);
421  tableModel.resync();
422  setButtonStates();
423  } else {
424  currentKeywordList = null;
425  tableModel.resync();
426  setButtonStates();
427  }
428  }
429 
430  @Override
431  public void store() {
432  // Implemented by parent panel
433  }
434 
435  @Override
436  public void load() {
437  // Implemented by parent panel
438  }
439 
440  KeywordList getCurrentKeywordList() {
441  return currentKeywordList;
442  }
443 
444  void setCurrentKeywordList(KeywordList list) {
445  currentKeywordList = list;
446  }
447 
448  private class KeywordTableModel extends AbstractTableModel {
449 
450  @Override
451  public int getColumnCount() {
452  return 2;
453  }
454 
455  @Override
456  public int getRowCount() {
457  return currentKeywordList == null ? 0 : currentKeywordList.getKeywords().size();
458  }
459 
460  @Override
461  public String getColumnName(int column) {
462  String colName = null;
463 
464  switch (column) {
465  case 0:
466  colName = NbBundle.getMessage(this.getClass(), "KeywordSearchEditListPanel.kwColName");
467  break;
468  case 1:
469  colName = NbBundle.getMessage(this.getClass(), "KeywordSearch.typeColLbl");
470  break;
471  default:
472  ;
473  }
474  return colName;
475  }
476 
477  @Override
478  public Object getValueAt(int rowIndex, int columnIndex) {
479  Object ret = null;
480  if (currentKeywordList == null) {
481  return "";
482  }
483  Keyword word = currentKeywordList.getKeywords().get(rowIndex);
484  switch (columnIndex) {
485  case 0:
486  ret = word.getSearchTerm();
487  break;
488  case 1:
489  ret = word.getSearchTermType();
490  break;
491  default:
492  logger.log(Level.SEVERE, "Invalid table column index: {0}", columnIndex); //NON-NLS
493  break;
494  }
495  return ret;
496  }
497 
498  @Override
499  public boolean isCellEditable(int rowIndex, int columnIndex) {
500  return false;
501  }
502 
503  @Override
504  public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
505  }
506 
507  @Override
508  public Class<?> getColumnClass(int c) {
509  return getValueAt(0, c).getClass();
510  }
511 
512  void addKeyword(Keyword keyword) {
513  if (!currentKeywordList.hasKeyword(keyword)) {
514  currentKeywordList.getKeywords().add(keyword);
515  }
516  fireTableDataChanged();
517  }
518 
519  void resync() {
520  fireTableDataChanged();
521  }
522 
523  //delete selected from handle, events are fired from the handle
524  void deleteSelected(int[] selected) {
525  List<Keyword> words = currentKeywordList.getKeywords();
526  Arrays.sort(selected);
527  for (int arrayi = selected.length - 1; arrayi >= 0; arrayi--) {
528  words.remove(selected[arrayi]);
529  }
530  resync();
531  }
532  }
533 
537  void setFocusOnKeywordTextBox() {
538  newKeywordsButton.requestFocus();
539  }
540 }

Copyright © 2012-2016 Basis Technology. Generated on: Mon Apr 24 2017
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.