19 package org.sleuthkit.autopsy.keywordsearch;
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;
45 @SuppressWarnings(
"PMD.SingularField")
46 class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionListener, OptionsPanel {
48 private static final Logger logger = Logger.getLogger(GlobalEditListPanel.class.getName());
49 private static final long serialVersionUID = 1L;
50 private final KeywordTableModel tableModel;
51 private KeywordList currentKeywordList;
56 GlobalEditListPanel() {
57 tableModel =
new KeywordTableModel();
59 customizeComponents();
62 private void customizeComponents() {
63 newKeywordsButton.setToolTipText((NbBundle.getMessage(
this.getClass(),
"KeywordSearchEditListPanel.customizeComponents.addWordToolTip")));
64 deleteWordButton.setToolTipText(NbBundle.getMessage(
this.getClass(),
"KeywordSearchEditListPanel.customizeComponents.removeSelectedMsg"));
66 keywordTable.getParent().setBackground(keywordTable.getBackground());
67 final int width = jScrollPane1.getPreferredSize().width;
68 keywordTable.setAutoResizeMode(JTable.AUTO_RESIZE_NEXT_COLUMN);
70 for (
int i = 0; i < keywordTable.getColumnCount(); i++) {
71 column = keywordTable.getColumnModel().getColumn(i);
73 column.setPreferredWidth(((
int) (width * 0.90)));
75 column.setPreferredWidth(((
int) (width * 0.10)));
78 keywordTable.setCellSelectionEnabled(
false);
79 keywordTable.setRowSelectionAllowed(
true);
80 keywordTable.setDefaultRenderer(String.class,
new SimpleTableCellRenderer());
82 final ListSelectionModel lsm = keywordTable.getSelectionModel();
83 lsm.addListSelectionListener(
new ListSelectionListener() {
85 public void valueChanged(ListSelectionEvent e) {
86 boolean canDelete = !(lsm.isSelectionEmpty() || currentKeywordList.isEditable() || IngestManager.getInstance().isIngestRunning());
87 boolean canEdit = canDelete && (lsm.getMaxSelectionIndex() == lsm.getMinSelectionIndex());
88 deleteWordButton.setEnabled(canDelete);
89 editWordButton.setEnabled(canEdit);
95 IngestManager.getInstance().addIngestJobEventListener(
new PropertyChangeListener() {
97 public void propertyChange(PropertyChangeEvent evt) {
98 Object source = evt.getSource();
99 if (source instanceof String && ((String) source).equals(
"LOCAL")) {
100 EventQueue.invokeLater(() -> {
111 void setButtonStates() {
112 boolean isIngestRunning = IngestManager.getInstance().isIngestRunning();
113 boolean isListSelected = currentKeywordList != null;
115 ingestWarningLabel.setVisible(isIngestRunning);
117 boolean canEditList = isListSelected && !isIngestRunning;
118 ingestMessagesCheckbox.setEnabled(canEditList);
119 ingestMessagesCheckbox.setSelected(currentKeywordList != null && currentKeywordList.getIngestMessages());
122 boolean canAddWord = canEditList && !currentKeywordList.isEditable();
123 newKeywordsButton.setEnabled(canAddWord);
126 if ((currentKeywordList == null) || (currentKeywordList.getKeywords().isEmpty())) {
127 deleteWordButton.setEnabled(
false);
128 editWordButton.setEnabled(
false);
132 @NbBundle.Messages({
"GlobalEditListPanel.editKeyword.title=Edit Keyword",
133 "GlobalEditListPanel.warning.title=Warning",
134 "GlobalEditListPanel.warning.text=Boundary characters ^ and $ do not match word boundaries. Consider\nreplacing with an explicit list of boundary characters, such as [ \\.,]"})
142 private boolean addKeywordsAction(String existingKeywords,
boolean isLiteral,
boolean isWholeWord) {
143 String keywordsToRedisplay = existingKeywords;
144 AddKeywordsDialog dialog =
new AddKeywordsDialog();
150 if (!existingKeywords.isEmpty()) {
151 dialog.setTitle(NbBundle.getMessage(GlobalEditListPanel.class,
"GlobalEditListPanel.editKeyword.title"));
153 while (badCount > 0) {
154 dialog.setInitialKeywordList(keywordsToRedisplay, isLiteral, isWholeWord);
160 keywordsToRedisplay =
"";
161 boolean displayedBoundaryWarning =
false;
163 if (!dialog.getKeywords().isEmpty()) {
165 for (String newWord : dialog.getKeywords()) {
166 if (newWord.isEmpty()) {
170 final Keyword keyword =
new Keyword(newWord, !dialog.isKeywordRegex(), dialog.isKeywordExact(), currentKeywordList.getName(), newWord);
171 if (currentKeywordList.hasKeyword(keyword)) {
177 if (( ! displayedBoundaryWarning) && dialog.isKeywordRegex()) {
178 if(newWord.startsWith(
"^") ||
179 (newWord.endsWith(
"$") && ! newWord.endsWith(
"\\$"))) {
181 KeywordSearchUtil.displayDialog(NbBundle.getMessage(
this.getClass(),
"GlobalEditListPanel.warning.title"),
182 NbBundle.getMessage(
this.getClass(),
"GlobalEditListPanel.warning.text"),
183 KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN);
185 displayedBoundaryWarning =
true;
190 boolean valid =
true;
192 Pattern.compile(newWord);
193 }
catch (PatternSyntaxException ex1) {
195 }
catch (IllegalArgumentException ex2) {
201 keywordsToRedisplay += newWord +
"\n";
207 tableModel.addKeyword(keyword);
210 XmlKeywordSearchList.getCurrent().addList(currentKeywordList);
211 firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
213 if ((badCount > 0) || (dupeCount > 0)) {
219 KeywordSearchUtil.DIALOG_MESSAGE_TYPE level = KeywordSearchUtil.DIALOG_MESSAGE_TYPE.INFO;
222 summary += NbBundle.getMessage(GlobalEditListPanel.class,
"GlobalEditListPanel.keywordsAddedPlural.text", goodCount) +
"\n";
224 summary += NbBundle.getMessage(GlobalEditListPanel.class,
"GlobalEditListPanel.keywordsAdded.text", goodCount) +
"\n";
229 summary += NbBundle.getMessage(GlobalEditListPanel.class,
"GlobalEditListPanel.keywordDupesSkippedPlural.text", dupeCount) +
"\n";
231 summary += NbBundle.getMessage(GlobalEditListPanel.class,
"GlobalEditListPanel.keywordDupesSkipped.text", dupeCount) +
"\n";
233 level = KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN;
237 summary += NbBundle.getMessage(GlobalEditListPanel.class,
"GlobalEditListPanel.keywordErrorsPlural.text", badCount) +
"\n";
239 summary += NbBundle.getMessage(GlobalEditListPanel.class,
"GlobalEditListPanel.keywordErrors.text", badCount) +
"\n";
241 level = KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR;
243 KeywordSearchUtil.displayDialog(NbBundle.getMessage(
this.getClass(),
"GlobalEditListPanel.addKeywordResults.text"),
248 setFocusOnKeywordTextBox();
250 return (goodCount >= 1 && dupeCount == 0);
259 private void deleteKeywordAction(
int[] selectedKeywords) {
260 tableModel.deleteSelected(selectedKeywords);
261 XmlKeywordSearchList.getCurrent().addList(currentKeywordList);
270 @SuppressWarnings(
"unchecked")
272 private
void initComponents() {
274 listEditorPanel =
new javax.swing.JPanel();
275 jScrollPane1 =
new javax.swing.JScrollPane();
276 keywordTable =
new javax.swing.JTable();
277 ingestMessagesCheckbox =
new javax.swing.JCheckBox();
278 keywordsLabel =
new javax.swing.JLabel();
279 newKeywordsButton =
new javax.swing.JButton();
280 deleteWordButton =
new javax.swing.JButton();
281 editWordButton =
new javax.swing.JButton();
282 ingestWarningLabel =
new javax.swing.JLabel();
284 setMinimumSize(
new java.awt.Dimension(0, 0));
286 listEditorPanel.setMinimumSize(
new java.awt.Dimension(0, 0));
288 jScrollPane1.setPreferredSize(
new java.awt.Dimension(340, 300));
290 keywordTable.setModel(tableModel);
291 keywordTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_OFF);
292 keywordTable.setGridColor(
new java.awt.Color(153, 153, 153));
293 keywordTable.setMaximumSize(
new java.awt.Dimension(30000, 30000));
294 keywordTable.getTableHeader().setReorderingAllowed(
false);
295 jScrollPane1.setViewportView(keywordTable);
297 ingestMessagesCheckbox.setSelected(
true);
298 ingestMessagesCheckbox.setText(
org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class,
"KeywordSearchEditListPanel.ingestMessagesCheckbox.text"));
299 ingestMessagesCheckbox.setToolTipText(
org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class,
"KeywordSearchEditListPanel.ingestMessagesCheckbox.toolTipText"));
300 ingestMessagesCheckbox.addActionListener(
new java.awt.event.ActionListener() {
301 public void actionPerformed(java.awt.event.ActionEvent evt) {
302 ingestMessagesCheckboxActionPerformed(evt);
306 keywordsLabel.setText(
org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class,
"KeywordSearchEditListPanel.keywordsLabel.text"));
308 newKeywordsButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/keywordsearch/add16.png")));
309 newKeywordsButton.setText(
org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class,
"GlobalEditListPanel.newKeywordsButton.text"));
310 newKeywordsButton.addActionListener(
new java.awt.event.ActionListener() {
311 public void actionPerformed(java.awt.event.ActionEvent evt) {
312 newKeywordsButtonActionPerformed(evt);
316 deleteWordButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/keywordsearch/delete16.png")));
317 deleteWordButton.setText(
org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class,
"KeywordSearchEditListPanel.deleteWordButton.text"));
318 deleteWordButton.addActionListener(
new java.awt.event.ActionListener() {
319 public void actionPerformed(java.awt.event.ActionEvent evt) {
320 deleteWordButtonActionPerformed(evt);
324 editWordButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/keywordsearch/edit16.png")));
325 editWordButton.setText(
org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class,
"GlobalEditListPanel.editWordButton.text"));
326 editWordButton.addActionListener(
new java.awt.event.ActionListener() {
327 public void actionPerformed(java.awt.event.ActionEvent evt) {
328 editWordButtonActionPerformed(evt);
332 ingestWarningLabel.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/modules/hashdatabase/warning16.png")));
333 ingestWarningLabel.setText(
org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class,
"GlobalEditListPanel.ingestWarningLabel.text"));
335 javax.swing.GroupLayout listEditorPanelLayout =
new javax.swing.GroupLayout(listEditorPanel);
336 listEditorPanel.setLayout(listEditorPanelLayout);
337 listEditorPanelLayout.setHorizontalGroup(
338 listEditorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
339 .addGroup(listEditorPanelLayout.createSequentialGroup()
341 .addGroup(listEditorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
342 .addGroup(listEditorPanelLayout.createSequentialGroup()
343 .addComponent(keywordsLabel)
344 .addGap(0, 0, Short.MAX_VALUE))
345 .addGroup(listEditorPanelLayout.createSequentialGroup()
347 .addGroup(listEditorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
348 .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 566, Short.MAX_VALUE)
349 .addGroup(listEditorPanelLayout.createSequentialGroup()
350 .addComponent(newKeywordsButton)
352 .addComponent(editWordButton)
354 .addComponent(deleteWordButton)
355 .addGap(0, 0, Short.MAX_VALUE))
356 .addGroup(listEditorPanelLayout.createSequentialGroup()
357 .addComponent(ingestMessagesCheckbox)
358 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
359 .addComponent(ingestWarningLabel)))))
363 listEditorPanelLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL,
new java.awt.Component[] {deleteWordButton, editWordButton, newKeywordsButton});
365 listEditorPanelLayout.setVerticalGroup(
366 listEditorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
367 .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, listEditorPanelLayout.createSequentialGroup()
369 .addComponent(keywordsLabel)
370 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
371 .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 256, Short.MAX_VALUE)
372 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
373 .addGroup(listEditorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
374 .addComponent(deleteWordButton)
375 .addComponent(newKeywordsButton)
376 .addComponent(editWordButton))
377 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
378 .addGroup(listEditorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
379 .addComponent(ingestMessagesCheckbox)
380 .addComponent(ingestWarningLabel))
384 javax.swing.GroupLayout layout =
new javax.swing.GroupLayout(
this);
385 this.setLayout(layout);
386 layout.setHorizontalGroup(
387 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
388 .addComponent(listEditorPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
390 layout.setVerticalGroup(
391 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
392 .addGroup(layout.createSequentialGroup()
393 .addComponent(listEditorPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
398 private void deleteWordButtonActionPerformed(java.awt.event.ActionEvent evt) {
399 if (KeywordSearchUtil.displayConfirmDialog(NbBundle.getMessage(
this.getClass(),
"KeywordSearchEditListPanel.removeKwMsg"),
400 NbBundle.getMessage(
this.getClass(),
"KeywordSearchEditListPanel.deleteWordButtonActionPerformed.delConfirmMsg"),
401 KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN)) {
402 deleteKeywordAction(keywordTable.getSelectedRows());
403 firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
407 private void ingestMessagesCheckboxActionPerformed(java.awt.event.ActionEvent evt) {
408 currentKeywordList.setIngestMessages(ingestMessagesCheckbox.isSelected());
409 XmlKeywordSearchList updater = XmlKeywordSearchList.getCurrent();
410 updater.addList(currentKeywordList);
411 firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
414 private void newKeywordsButtonActionPerformed(java.awt.event.ActionEvent evt) {
415 addKeywordsAction(
"",
true,
true);
418 private void editWordButtonActionPerformed(java.awt.event.ActionEvent evt) {
419 int[] selectedKeywords = keywordTable.getSelectedRows();
420 if (selectedKeywords.length == 1) {
421 Keyword currentKeyword = currentKeywordList.getKeywords().get(selectedKeywords[0]);
422 if (addKeywordsAction(currentKeyword.getSearchTerm(), currentKeyword.searchTermIsLiteral(), currentKeyword.searchTermIsWholeWord())) {
423 deleteKeywordAction(selectedKeywords);
429 private javax.swing.JButton deleteWordButton;
430 private javax.swing.JButton editWordButton;
431 private javax.swing.JCheckBox ingestMessagesCheckbox;
432 private javax.swing.JLabel ingestWarningLabel;
433 private javax.swing.JScrollPane jScrollPane1;
434 private javax.swing.JTable keywordTable;
435 private javax.swing.JLabel keywordsLabel;
436 private javax.swing.JPanel listEditorPanel;
437 private javax.swing.JButton newKeywordsButton;
441 public void valueChanged(ListSelectionEvent e) {
443 ListSelectionModel listSelectionModel = (ListSelectionModel) e.getSource();
444 currentKeywordList = null;
445 if (!listSelectionModel.isSelectionEmpty()) {
446 XmlKeywordSearchList loader = XmlKeywordSearchList.getCurrent();
447 if (listSelectionModel.getMinSelectionIndex() == listSelectionModel.getMaxSelectionIndex()) {
448 currentKeywordList = loader.getListsL(
false).get(listSelectionModel.getMinSelectionIndex());
456 public void store() {
465 KeywordList getCurrentKeywordList() {
466 return currentKeywordList;
469 void setCurrentKeywordList(KeywordList list) {
470 currentKeywordList = list;
482 return currentKeywordList == null ? 0 : currentKeywordList.getKeywords().size();
487 String colName = null;
491 colName = NbBundle.getMessage(this.getClass(),
"KeywordSearchEditListPanel.kwColName");
494 colName = NbBundle.getMessage(this.getClass(),
"KeywordSearch.typeColLbl");
505 if (currentKeywordList == null) {
508 Keyword word = currentKeywordList.getKeywords().get(rowIndex);
509 switch (columnIndex) {
514 ret = word.getSearchTermType();
517 logger.log(Level.SEVERE,
"Invalid table column index: {0}", columnIndex);
529 public void setValueAt(Object aValue,
int rowIndex,
int columnIndex) {
534 return getValueAt(0, c).getClass();
537 void addKeyword(
Keyword keyword) {
538 if (!currentKeywordList.hasKeyword(keyword)) {
539 currentKeywordList.getKeywords().add(keyword);
541 fireTableDataChanged();
545 fireTableDataChanged();
549 void deleteSelected(
int[] selected) {
550 List<Keyword> words = currentKeywordList.getKeywords();
551 Arrays.sort(selected);
552 for (
int arrayi = selected.length - 1; arrayi >= 0; arrayi--) {
553 words.remove(selected[arrayi]);
562 void setFocusOnKeywordTextBox() {
563 newKeywordsButton.requestFocus();
boolean isCellEditable(int rowIndex, int columnIndex)
void setValueAt(Object aValue, int rowIndex, int columnIndex)
String getColumnName(int column)
Class<?> getColumnClass(int c)
Object getValueAt(int rowIndex, int columnIndex)