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;
44 @SuppressWarnings(
"PMD.SingularField")
45 class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionListener, OptionsPanel {
47 private static final Logger logger = Logger.getLogger(GlobalEditListPanel.class.getName());
48 private static final long serialVersionUID = 1L;
49 private final KeywordTableModel tableModel;
50 private KeywordList currentKeywordList;
55 GlobalEditListPanel() {
56 tableModel =
new KeywordTableModel();
58 customizeComponents();
61 private void customizeComponents() {
62 newKeywordsButton.setToolTipText((NbBundle.getMessage(
this.getClass(),
"KeywordSearchEditListPanel.customizeComponents.addWordToolTip")));
63 deleteWordButton.setToolTipText(NbBundle.getMessage(
this.getClass(),
"KeywordSearchEditListPanel.customizeComponents.removeSelectedMsg"));
65 keywordTable.getParent().setBackground(keywordTable.getBackground());
66 final int width = jScrollPane1.getPreferredSize().width;
67 keywordTable.setAutoResizeMode(JTable.AUTO_RESIZE_NEXT_COLUMN);
69 for (
int i = 0; i < keywordTable.getColumnCount(); i++) {
70 column = keywordTable.getColumnModel().getColumn(i);
72 column.setPreferredWidth(((
int) (width * 0.90)));
74 column.setPreferredWidth(((
int) (width * 0.10)));
77 keywordTable.setCellSelectionEnabled(
false);
78 keywordTable.setRowSelectionAllowed(
true);
80 final ListSelectionModel lsm = keywordTable.getSelectionModel();
81 lsm.addListSelectionListener(
new ListSelectionListener() {
83 public void valueChanged(ListSelectionEvent e) {
84 boolean canDelete = !(lsm.isSelectionEmpty() || currentKeywordList.isEditable() || IngestManager.getInstance().isIngestRunning());
85 boolean canEdit = canDelete && (lsm.getMaxSelectionIndex() == lsm.getMinSelectionIndex());
86 deleteWordButton.setEnabled(canDelete);
87 editWordButton.setEnabled(canEdit);
93 IngestManager.getInstance().addIngestJobEventListener(
new PropertyChangeListener() {
95 public void propertyChange(PropertyChangeEvent evt) {
96 Object source = evt.getSource();
97 if (source instanceof String && ((String) source).equals(
"LOCAL")) {
98 EventQueue.invokeLater(() -> {
109 void setButtonStates() {
110 boolean isIngestRunning = IngestManager.getInstance().isIngestRunning();
111 boolean isListSelected = currentKeywordList != null;
113 ingestWarningLabel.setVisible(isIngestRunning);
115 boolean canEditList = isListSelected && !isIngestRunning;
116 ingestMessagesCheckbox.setEnabled(canEditList);
117 ingestMessagesCheckbox.setSelected(currentKeywordList != null && currentKeywordList.getIngestMessages());
120 boolean canAddWord = canEditList && !currentKeywordList.isEditable();
121 newKeywordsButton.setEnabled(canAddWord);
124 if ((currentKeywordList == null) || (currentKeywordList.getKeywords().isEmpty())) {
125 deleteWordButton.setEnabled(
false);
126 editWordButton.setEnabled(
false);
130 @NbBundle.Messages({
"GlobalEditListPanel.editKeyword.title=Edit Keyword",
131 "GlobalEditListPanel.warning.title=Warning",
132 "GlobalEditListPanel.warning.text=Boundary characters ^ and $ do not match word boundaries. Consider\nreplacing with an explicit list of boundary characters, such as [ \\.,]"})
140 private boolean addKeywordsAction(String existingKeywords,
boolean isLiteral,
boolean isWholeWord) {
141 String keywordsToRedisplay = existingKeywords;
142 AddKeywordsDialog dialog =
new AddKeywordsDialog();
148 if (!existingKeywords.isEmpty()) {
149 dialog.setTitle(NbBundle.getMessage(GlobalEditListPanel.class,
"GlobalEditListPanel.editKeyword.title"));
151 while (badCount > 0) {
152 dialog.setInitialKeywordList(keywordsToRedisplay, isLiteral, isWholeWord);
158 keywordsToRedisplay =
"";
159 boolean displayedBoundaryWarning =
false;
161 if (!dialog.getKeywords().isEmpty()) {
163 for (String newWord : dialog.getKeywords()) {
164 if (newWord.isEmpty()) {
168 final Keyword keyword =
new Keyword(newWord, !dialog.isKeywordRegex(), dialog.isKeywordExact(), currentKeywordList.getName(), newWord);
169 if (currentKeywordList.hasKeyword(keyword)) {
175 if (( ! displayedBoundaryWarning) && dialog.isKeywordRegex()) {
176 if(newWord.startsWith(
"^") ||
177 (newWord.endsWith(
"$") && ! newWord.endsWith(
"\\$"))) {
179 KeywordSearchUtil.displayDialog(NbBundle.getMessage(
this.getClass(),
"GlobalEditListPanel.warning.title"),
180 NbBundle.getMessage(
this.getClass(),
"GlobalEditListPanel.warning.text"),
181 KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN);
183 displayedBoundaryWarning =
true;
188 boolean valid =
true;
190 Pattern.compile(newWord);
191 }
catch (PatternSyntaxException ex1) {
193 }
catch (IllegalArgumentException ex2) {
199 keywordsToRedisplay += newWord +
"\n";
205 tableModel.addKeyword(keyword);
208 XmlKeywordSearchList.getCurrent().addList(currentKeywordList);
209 firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
211 if ((badCount > 0) || (dupeCount > 0)) {
217 KeywordSearchUtil.DIALOG_MESSAGE_TYPE level = KeywordSearchUtil.DIALOG_MESSAGE_TYPE.INFO;
220 summary += NbBundle.getMessage(GlobalEditListPanel.class,
"GlobalEditListPanel.keywordsAddedPlural.text", goodCount) +
"\n";
222 summary += NbBundle.getMessage(GlobalEditListPanel.class,
"GlobalEditListPanel.keywordsAdded.text", goodCount) +
"\n";
227 summary += NbBundle.getMessage(GlobalEditListPanel.class,
"GlobalEditListPanel.keywordDupesSkippedPlural.text", dupeCount) +
"\n";
229 summary += NbBundle.getMessage(GlobalEditListPanel.class,
"GlobalEditListPanel.keywordDupesSkipped.text", dupeCount) +
"\n";
231 level = KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN;
235 summary += NbBundle.getMessage(GlobalEditListPanel.class,
"GlobalEditListPanel.keywordErrorsPlural.text", badCount) +
"\n";
237 summary += NbBundle.getMessage(GlobalEditListPanel.class,
"GlobalEditListPanel.keywordErrors.text", badCount) +
"\n";
239 level = KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR;
241 KeywordSearchUtil.displayDialog(NbBundle.getMessage(
this.getClass(),
"GlobalEditListPanel.addKeywordResults.text"),
246 setFocusOnKeywordTextBox();
248 return (goodCount >= 1 && dupeCount == 0);
257 private void deleteKeywordAction(
int[] selectedKeywords) {
258 tableModel.deleteSelected(selectedKeywords);
259 XmlKeywordSearchList.getCurrent().addList(currentKeywordList);
268 @SuppressWarnings(
"unchecked")
270 private
void initComponents() {
272 listEditorPanel =
new javax.swing.JPanel();
273 jScrollPane1 =
new javax.swing.JScrollPane();
274 keywordTable =
new javax.swing.JTable();
275 ingestMessagesCheckbox =
new javax.swing.JCheckBox();
276 keywordsLabel =
new javax.swing.JLabel();
277 newKeywordsButton =
new javax.swing.JButton();
278 deleteWordButton =
new javax.swing.JButton();
279 editWordButton =
new javax.swing.JButton();
280 ingestWarningLabel =
new javax.swing.JLabel();
282 setMinimumSize(
new java.awt.Dimension(0, 0));
284 listEditorPanel.setMinimumSize(
new java.awt.Dimension(0, 0));
286 jScrollPane1.setPreferredSize(
new java.awt.Dimension(340, 300));
288 keywordTable.setModel(tableModel);
289 keywordTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_OFF);
290 keywordTable.setGridColor(
new java.awt.Color(153, 153, 153));
291 keywordTable.setMaximumSize(
new java.awt.Dimension(30000, 30000));
292 keywordTable.getTableHeader().setReorderingAllowed(
false);
293 jScrollPane1.setViewportView(keywordTable);
295 ingestMessagesCheckbox.setSelected(
true);
296 ingestMessagesCheckbox.setText(
org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class,
"KeywordSearchEditListPanel.ingestMessagesCheckbox.text"));
297 ingestMessagesCheckbox.setToolTipText(
org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class,
"KeywordSearchEditListPanel.ingestMessagesCheckbox.toolTipText"));
298 ingestMessagesCheckbox.addActionListener(
new java.awt.event.ActionListener() {
299 public void actionPerformed(java.awt.event.ActionEvent evt) {
300 ingestMessagesCheckboxActionPerformed(evt);
304 keywordsLabel.setText(
org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class,
"KeywordSearchEditListPanel.keywordsLabel.text"));
306 newKeywordsButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/keywordsearch/add16.png")));
307 newKeywordsButton.setText(
org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class,
"GlobalEditListPanel.newKeywordsButton.text"));
308 newKeywordsButton.addActionListener(
new java.awt.event.ActionListener() {
309 public void actionPerformed(java.awt.event.ActionEvent evt) {
310 newKeywordsButtonActionPerformed(evt);
314 deleteWordButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/keywordsearch/delete16.png")));
315 deleteWordButton.setText(
org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class,
"KeywordSearchEditListPanel.deleteWordButton.text"));
316 deleteWordButton.addActionListener(
new java.awt.event.ActionListener() {
317 public void actionPerformed(java.awt.event.ActionEvent evt) {
318 deleteWordButtonActionPerformed(evt);
322 editWordButton.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/keywordsearch/edit16.png")));
323 editWordButton.setText(
org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class,
"GlobalEditListPanel.editWordButton.text"));
324 editWordButton.addActionListener(
new java.awt.event.ActionListener() {
325 public void actionPerformed(java.awt.event.ActionEvent evt) {
326 editWordButtonActionPerformed(evt);
330 ingestWarningLabel.setFont(ingestWarningLabel.getFont().deriveFont(ingestWarningLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
331 ingestWarningLabel.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/modules/hashdatabase/warning16.png")));
332 ingestWarningLabel.setText(
org.openide.util.NbBundle.getMessage(GlobalEditListPanel.class,
"GlobalEditListPanel.ingestWarningLabel.text"));
334 javax.swing.GroupLayout listEditorPanelLayout =
new javax.swing.GroupLayout(listEditorPanel);
335 listEditorPanel.setLayout(listEditorPanelLayout);
336 listEditorPanelLayout.setHorizontalGroup(
337 listEditorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
338 .addGroup(listEditorPanelLayout.createSequentialGroup()
340 .addGroup(listEditorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
341 .addGroup(listEditorPanelLayout.createSequentialGroup()
342 .addComponent(keywordsLabel)
343 .addGap(0, 0, Short.MAX_VALUE))
344 .addGroup(listEditorPanelLayout.createSequentialGroup()
346 .addGroup(listEditorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
347 .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 566, Short.MAX_VALUE)
348 .addGroup(listEditorPanelLayout.createSequentialGroup()
349 .addComponent(newKeywordsButton)
351 .addComponent(editWordButton)
353 .addComponent(deleteWordButton)
354 .addGap(0, 0, Short.MAX_VALUE))
355 .addGroup(listEditorPanelLayout.createSequentialGroup()
356 .addComponent(ingestMessagesCheckbox)
357 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
358 .addComponent(ingestWarningLabel)))))
362 listEditorPanelLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL,
new java.awt.Component[] {deleteWordButton, editWordButton, newKeywordsButton});
364 listEditorPanelLayout.setVerticalGroup(
365 listEditorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
366 .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, listEditorPanelLayout.createSequentialGroup()
368 .addComponent(keywordsLabel)
369 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
370 .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 256, Short.MAX_VALUE)
371 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
372 .addGroup(listEditorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
373 .addComponent(deleteWordButton)
374 .addComponent(newKeywordsButton)
375 .addComponent(editWordButton))
376 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
377 .addGroup(listEditorPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
378 .addComponent(ingestMessagesCheckbox)
379 .addComponent(ingestWarningLabel))
383 javax.swing.GroupLayout layout =
new javax.swing.GroupLayout(
this);
384 this.setLayout(layout);
385 layout.setHorizontalGroup(
386 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
387 .addComponent(listEditorPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
389 layout.setVerticalGroup(
390 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
391 .addGroup(layout.createSequentialGroup()
392 .addComponent(listEditorPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
397 private void deleteWordButtonActionPerformed(java.awt.event.ActionEvent evt) {
398 if (KeywordSearchUtil.displayConfirmDialog(NbBundle.getMessage(
this.getClass(),
"KeywordSearchEditListPanel.removeKwMsg"),
399 NbBundle.getMessage(
this.getClass(),
"KeywordSearchEditListPanel.deleteWordButtonActionPerformed.delConfirmMsg"),
400 KeywordSearchUtil.DIALOG_MESSAGE_TYPE.WARN)) {
401 deleteKeywordAction(keywordTable.getSelectedRows());
402 firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
406 private void ingestMessagesCheckboxActionPerformed(java.awt.event.ActionEvent evt) {
407 currentKeywordList.setIngestMessages(ingestMessagesCheckbox.isSelected());
408 XmlKeywordSearchList updater = XmlKeywordSearchList.getCurrent();
409 updater.addList(currentKeywordList);
410 firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
413 private void newKeywordsButtonActionPerformed(java.awt.event.ActionEvent evt) {
414 addKeywordsAction(
"",
true,
true);
417 private void editWordButtonActionPerformed(java.awt.event.ActionEvent evt) {
418 int[] selectedKeywords = keywordTable.getSelectedRows();
419 if (selectedKeywords.length == 1) {
420 Keyword currentKeyword = currentKeywordList.getKeywords().get(selectedKeywords[0]);
421 if (addKeywordsAction(currentKeyword.getSearchTerm(), currentKeyword.searchTermIsLiteral(), currentKeyword.searchTermIsWholeWord())) {
422 deleteKeywordAction(selectedKeywords);
428 private javax.swing.JButton deleteWordButton;
429 private javax.swing.JButton editWordButton;
430 private javax.swing.JCheckBox ingestMessagesCheckbox;
431 private javax.swing.JLabel ingestWarningLabel;
432 private javax.swing.JScrollPane jScrollPane1;
433 private javax.swing.JTable keywordTable;
434 private javax.swing.JLabel keywordsLabel;
435 private javax.swing.JPanel listEditorPanel;
436 private javax.swing.JButton newKeywordsButton;
440 public void valueChanged(ListSelectionEvent e) {
442 ListSelectionModel listSelectionModel = (ListSelectionModel) e.getSource();
443 currentKeywordList = null;
444 if (!listSelectionModel.isSelectionEmpty()) {
445 XmlKeywordSearchList loader = XmlKeywordSearchList.getCurrent();
446 if (listSelectionModel.getMinSelectionIndex() == listSelectionModel.getMaxSelectionIndex()) {
447 currentKeywordList = loader.getListsL(
false).get(listSelectionModel.getMinSelectionIndex());
455 public void store() {
464 KeywordList getCurrentKeywordList() {
465 return currentKeywordList;
468 void setCurrentKeywordList(KeywordList list) {
469 currentKeywordList = list;
481 return currentKeywordList == null ? 0 : currentKeywordList.getKeywords().size();
486 String colName = null;
490 colName = NbBundle.getMessage(this.getClass(),
"KeywordSearchEditListPanel.kwColName");
493 colName = NbBundle.getMessage(this.getClass(),
"KeywordSearch.typeColLbl");
504 if (currentKeywordList == null) {
507 Keyword word = currentKeywordList.getKeywords().get(rowIndex);
508 switch (columnIndex) {
510 ret = word.getSearchTerm();
513 ret = word.getSearchTermType();
516 logger.log(Level.SEVERE,
"Invalid table column index: {0}", columnIndex);
528 public void setValueAt(Object aValue,
int rowIndex,
int columnIndex) {
533 return getValueAt(0, c).getClass();
536 void addKeyword(Keyword keyword) {
537 if (!currentKeywordList.hasKeyword(keyword)) {
538 currentKeywordList.getKeywords().add(keyword);
540 fireTableDataChanged();
544 fireTableDataChanged();
548 void deleteSelected(
int[] selected) {
549 List<Keyword> words = currentKeywordList.getKeywords();
550 Arrays.sort(selected);
551 for (
int arrayi = selected.length - 1; arrayi >= 0; arrayi--) {
552 words.remove(selected[arrayi]);
561 void setFocusOnKeywordTextBox() {
562 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)