Multiple keyword search - basic functionality (add keyword, search, escape literals)

This commit is contained in:
adam-m 2012-01-05 17:17:27 -05:00
parent 54758bf45a
commit 8fefd9b23d
9 changed files with 380 additions and 164 deletions

View File

@ -44,17 +44,13 @@ public class KeywordSearchDataExplorer implements DataExplorer {
this.tc = new KeywordSearchTabsTopComponent();
this.tc.addSearchButtonListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
tc.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
QueryType queryType = null;
if (tc.isLuceneQuerySelected()) {
queryType = QueryType.WORD;
} else {
queryType = QueryType.REGEX;
}
try {
search(tc.getQueryText(), queryType);
search();
} finally {
tc.setCursor(null);
}
@ -63,8 +59,6 @@ public class KeywordSearchDataExplorer implements DataExplorer {
KeywordSearch.changeSupport.addPropertyChangeListener(KeywordSearch.NUM_FILES_CHANGE_EVT, new IndexChangeListener());
}
private synchronized void setTheInstance() {
if (theInstance == null) {
@ -78,24 +72,28 @@ public class KeywordSearchDataExplorer implements DataExplorer {
* Executes a query and populates a DataResult tab with the results
* @param solrQuery
*/
private void search(String query, QueryType queryType) {
//TODO populate map with queries for keyword list search here
//Map<String, Boolean>qmap = new LinkedHashMap<String, Boolean>();
//qmap.put(query, Boolean.FALSE);
//KeywordSearchQueryManager man = new KeywordSearchQueryManager(query, queryType, Presentation.COLLAPSE);
KeywordSearchQueryManager man = new KeywordSearchQueryManager(query, queryType, Presentation.COLLAPSE);
private void search() {
KeywordSearchQueryManager man = null;
if (tc.isMultiwordQuery()) {
man = new KeywordSearchQueryManager(tc.getQueryList(), Presentation.COLLAPSE);
} else {
QueryType queryType = null;
if (tc.isLuceneQuerySelected()) {
queryType = QueryType.WORD;
} else {
queryType = QueryType.REGEX;
}
man = new KeywordSearchQueryManager(tc.getQueryText(), queryType, Presentation.COLLAPSE);
}
if (man.validate()) {
man.execute();
} else {
displayErrorDialog("Invalid query syntax." );
KeywordSearchUtil.displayDialog("Keyword Search Error", "Invalid query syntax.", KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR);
}
}
@Override
public org.openide.windows.TopComponent getTopComponent() {
return this.tc;
@ -105,17 +103,6 @@ public class KeywordSearchDataExplorer implements DataExplorer {
public void propertyChange(PropertyChangeEvent evt) {
}
private void displayErrorDialog(final String message) {
final Component parentComponent = null; // Use default window frame.
final String title = "Keyword Search Error";
final int messageType = JOptionPane.ERROR_MESSAGE;
JOptionPane.showMessageDialog(
parentComponent,
message,
title,
messageType);
}
class IndexChangeListener implements PropertyChangeListener {
@Override

View File

@ -17,90 +17,71 @@
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="filesIndexedNameLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="filesIndexedValLabel" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="searchButton" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="chLiteralWord" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="titleLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="loadListButton" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="addWordLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="1">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="titleLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="loadListButton" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
<Component id="saveListButton" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="chLiteralWord" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="addWordField" alignment="0" min="-2" pref="152" max="-2" attributes="0"/>
</Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="addWordButton" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace min="-2" pref="66" max="-2" attributes="0"/>
<Component id="deleteWordButton" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="deleteAllWordsButton" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="saveListButton" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="addWordField" min="-2" pref="152" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="31" max="-2" attributes="0"/>
<Component id="addWordButton" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="listLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="addWordLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="103" alignment="0" groupAlignment="1" max="-2" attributes="0">
<Group type="102" alignment="0" attributes="1">
<Component id="deleteWordButton" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
<Component id="deleteAllWordsButton" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="jScrollPane1" alignment="0" min="-2" pref="217" max="-2" attributes="0"/>
<Component id="searchButton" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="filesIndexedNameLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="filesIndexedValLabel" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="jScrollPane1" alignment="0" min="-2" pref="272" max="-2" attributes="0"/>
</Group>
<EmptySpace pref="15" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="titleLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="loadListButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="saveListButton" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="loadListButton" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="19" max="-2" attributes="0"/>
<Component id="addWordLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Group type="103" groupAlignment="1" attributes="0">
<Group type="102" attributes="0">
<Group type="103" groupAlignment="3" attributes="0">
<Component id="addWordButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="addWordField" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="27" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="1" attributes="0">
<Component id="chLiteralWord" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
</Group>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="addWordField" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="addWordButton" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="12" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="chLiteralWord" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="9" max="-2" attributes="0"/>
<Component id="listLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="jScrollPane1" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="jScrollPane1" min="-2" pref="220" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="28" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="deleteWordButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="deleteAllWordsButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="saveListButton" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="30" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="29" max="-2" attributes="0"/>
<Component id="searchButton" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="38" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="filesIndexedNameLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="filesIndexedValLabel" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="42" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="46" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -130,22 +111,6 @@
</Property>
</Properties>
</Component>
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JList" name="jList1">
<Properties>
<Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.editors2.ListModelEditor">
<StringArray count="0"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JLabel" name="titleLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
@ -197,6 +162,9 @@
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="KeywordSearchListTopComponent.deleteWordButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="deleteWordButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="deleteAllWordsButton">
<Properties>
@ -225,5 +193,23 @@
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="chLiteralWordActionPerformed"/>
</Events>
</Component>
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTable" name="keywordTable">
<Properties>
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="tableModel" type="code"/>
</Property>
<Property name="showHorizontalLines" type="boolean" value="false"/>
<Property name="showVerticalLines" type="boolean" value="false"/>
</Properties>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Form>

View File

@ -16,11 +16,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.keywordsearch;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn;
import org.openide.util.NbBundle;
import org.openide.windows.TopComponent;
import org.netbeans.api.settings.ConvertAsProperties;
@ -43,25 +51,57 @@ preferredID = "KeywordSearchListTopComponent")
public final class KeywordSearchListTopComponent extends TopComponent implements KeywordSearchTopComponentInterface {
private Logger logger = Logger.getLogger(KeywordSearchListTopComponent.class.getName());
private KeywordTableModel tableModel;
public KeywordSearchListTopComponent() {
tableModel = new KeywordTableModel();
initComponents();
customizeComponents();
setName(NbBundle.getMessage(KeywordSearchListTopComponent.class, "CTL_KeywordSearchListTopComponent"));
setToolTipText(NbBundle.getMessage(KeywordSearchListTopComponent.class, "HINT_KeywordSearchListTopComponent"));
}
private void customizeComponents() {
chLiteralWord.setToolTipText("Literal word (auto-escape special regex characters)");
chLiteralWord.setToolTipText("Literal word (auto-escape special characters)");
addWordButton.setToolTipText(("Add a new word to the keyword search list"));
addWordField.setToolTipText("Enter a new word or regex to search");
loadListButton.setToolTipText("Load a new keyword list from file");
saveListButton.setToolTipText("Save the current keyword list to a file");
searchButton.setToolTipText("Execute the keyword list search using the current list");
deleteWordButton.setToolTipText("Delete selected word(s) from the list");
deleteAllWordsButton.setToolTipText("Delete all words from the list (clear it)");
deleteWordButton.setToolTipText("Delete selected keyword(s) from the list");
deleteAllWordsButton.setToolTipText("Delete all keywords from the list (clear it)");
keywordTable.setAutoscrolls(true);
keywordTable.setTableHeader(null);
keywordTable.setShowHorizontalLines(false);
keywordTable.setShowVerticalLines(false);
keywordTable.setShowGrid(false);
//TODO removing dotted line of selected cell might require custom renderer
final int width = keywordTable.getSize().width;
TableColumn column = null;
for (int i = 0; i < 2; i++) {
column = keywordTable.getColumnModel().getColumn(i);
if (i == 1) {
column.setPreferredWidth(((int) (width * 0.2)));
//column.setCellEditor(new DefaultCellEditor(new JCheckBox()));
} else {
column.setPreferredWidth(((int) (width * 0.7)));
}
}
keywordTable.setCellSelectionEnabled(false);
//keywordTable.setBorder(BorderFactory.createEmptyBorder());
//create some empty rows
tableModel.initEmpty();
//test
tableModel.addKeyword("\\d\\d\\d-\\d\\d\\d-\\d\\d\\d\\d");
tableModel.addKeyword("\\d\\d\\.\\d\\d\\d\\.*");
tableModel.addKeyword("text");
}
@ -76,8 +116,6 @@ public final class KeywordSearchListTopComponent extends TopComponent implements
searchButton = new javax.swing.JButton();
filesIndexedNameLabel = new javax.swing.JLabel();
filesIndexedValLabel = new javax.swing.JLabel();
jScrollPane1 = new javax.swing.JScrollPane();
jList1 = new javax.swing.JList();
titleLabel = new javax.swing.JLabel();
listLabel = new javax.swing.JLabel();
addWordField = new javax.swing.JTextField();
@ -88,6 +126,8 @@ public final class KeywordSearchListTopComponent extends TopComponent implements
deleteAllWordsButton = new javax.swing.JButton();
saveListButton = new javax.swing.JButton();
chLiteralWord = new javax.swing.JCheckBox();
jScrollPane1 = new javax.swing.JScrollPane();
keywordTable = new javax.swing.JTable();
org.openide.awt.Mnemonics.setLocalizedText(searchButton, org.openide.util.NbBundle.getMessage(KeywordSearchListTopComponent.class, "KeywordSearchListTopComponent.searchButton.text")); // NOI18N
searchButton.addActionListener(new java.awt.event.ActionListener() {
@ -100,8 +140,6 @@ public final class KeywordSearchListTopComponent extends TopComponent implements
org.openide.awt.Mnemonics.setLocalizedText(filesIndexedValLabel, org.openide.util.NbBundle.getMessage(KeywordSearchListTopComponent.class, "KeywordSearchListTopComponent.filesIndexedValLabel.text")); // NOI18N
jScrollPane1.setViewportView(jList1);
org.openide.awt.Mnemonics.setLocalizedText(titleLabel, org.openide.util.NbBundle.getMessage(KeywordSearchListTopComponent.class, "KeywordSearchListTopComponent.titleLabel.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(listLabel, org.openide.util.NbBundle.getMessage(KeywordSearchListTopComponent.class, "KeywordSearchListTopComponent.listLabel.text")); // NOI18N
@ -120,6 +158,11 @@ public final class KeywordSearchListTopComponent extends TopComponent implements
org.openide.awt.Mnemonics.setLocalizedText(loadListButton, org.openide.util.NbBundle.getMessage(KeywordSearchListTopComponent.class, "KeywordSearchListTopComponent.loadListButton.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(deleteWordButton, org.openide.util.NbBundle.getMessage(KeywordSearchListTopComponent.class, "KeywordSearchListTopComponent.deleteWordButton.text")); // NOI18N
deleteWordButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
deleteWordButtonActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(deleteAllWordsButton, org.openide.util.NbBundle.getMessage(KeywordSearchListTopComponent.class, "KeywordSearchListTopComponent.deleteAllWordsButton.text")); // NOI18N
@ -137,77 +180,72 @@ public final class KeywordSearchListTopComponent extends TopComponent implements
}
});
keywordTable.setModel(tableModel);
keywordTable.setShowHorizontalLines(false);
keywordTable.setShowVerticalLines(false);
jScrollPane1.setViewportView(keywordTable);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(chLiteralWord)
.addComponent(titleLabel)
.addComponent(loadListButton)
.addComponent(addWordLabel)
.addGroup(layout.createSequentialGroup()
.addComponent(filesIndexedNameLabel)
.addComponent(deleteWordButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(filesIndexedValLabel))
.addComponent(deleteAllWordsButton)
.addGap(18, 18, 18)
.addComponent(saveListButton))
.addGroup(layout.createSequentialGroup()
.addComponent(addWordField, javax.swing.GroupLayout.PREFERRED_SIZE, 152, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(31, 31, 31)
.addComponent(addWordButton))
.addComponent(listLabel)
.addComponent(searchButton)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(titleLabel)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addGroup(layout.createSequentialGroup()
.addComponent(loadListButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(saveListButton))
.addComponent(chLiteralWord)
.addComponent(addWordField, javax.swing.GroupLayout.PREFERRED_SIZE, 152, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(addWordButton)))
.addGap(66, 66, 66))
.addComponent(listLabel)
.addComponent(addWordLabel)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
.addComponent(deleteWordButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(deleteAllWordsButton))
.addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.PREFERRED_SIZE, 217, javax.swing.GroupLayout.PREFERRED_SIZE))))
.addComponent(filesIndexedNameLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(filesIndexedValLabel))
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 272, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap(15, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(titleLabel)
.addGap(18, 18, 18)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(loadListButton)
.addComponent(saveListButton))
.addComponent(loadListButton)
.addGap(19, 19, 19)
.addComponent(addWordLabel)
.addGap(18, 18, 18)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(addWordButton)
.addComponent(addWordField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(27, 27, 27))
.addGroup(layout.createSequentialGroup()
.addComponent(chLiteralWord)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)))
.addGap(12, 12, 12)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(addWordField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(addWordButton))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(chLiteralWord)
.addGap(9, 9, 9)
.addComponent(listLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 220, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(28, 28, 28)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(deleteWordButton)
.addComponent(deleteAllWordsButton))
.addGap(30, 30, 30)
.addComponent(deleteAllWordsButton)
.addComponent(saveListButton))
.addGap(29, 29, 29)
.addComponent(searchButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGap(38, 38, 38)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(filesIndexedNameLabel)
.addComponent(filesIndexedValLabel))
.addGap(42, 42, 42))
.addGap(46, 46, 46))
);
}// </editor-fold>//GEN-END:initComponents
@ -216,7 +254,43 @@ public final class KeywordSearchListTopComponent extends TopComponent implements
}//GEN-LAST:event_searchButtonActionPerformed
private void addWordButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addWordButtonActionPerformed
// TODO add your handling code here:
String newWord = addWordField.getText();
String newWordEscaped = Pattern.quote(newWord);
if (newWord.trim().equals("")) {
return;
} else if (keywordExists(newWord) || keywordExists(newWordEscaped)) {
KeywordSearchUtil.displayDialog("New Keyword Entry", "Keyword already exists in the list.", KeywordSearchUtil.DIALOG_MESSAGE_TYPE.INFO);
return;
}
String toAdd = null;
if (chLiteralWord.isSelected()) {
toAdd = newWordEscaped;
} else {
toAdd = newWord;
}
//check if valid
boolean valid = true;
try {
Pattern.compile(toAdd);
} catch (PatternSyntaxException ex1) {
valid = false;
} catch (IllegalArgumentException ex2) {
valid = false;
}
if (!valid) {
KeywordSearchUtil.displayDialog("New Keyword Entry", "Invalid keyword pattern. Use words or a correct regex pattern.", KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR);
return;
}
//add & reset checkbox
chLiteralWord.setSelected(false);
tableModel.addKeyword(toAdd);
addWordField.setText("");
}//GEN-LAST:event_addWordButtonActionPerformed
private void saveListButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveListButtonActionPerformed
@ -227,6 +301,9 @@ public final class KeywordSearchListTopComponent extends TopComponent implements
// TODO add your handling code here:
}//GEN-LAST:event_chLiteralWordActionPerformed
private void deleteWordButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteWordButtonActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_deleteWordButtonActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton addWordButton;
private javax.swing.JTextField addWordField;
@ -236,14 +313,15 @@ public final class KeywordSearchListTopComponent extends TopComponent implements
private javax.swing.JButton deleteWordButton;
private javax.swing.JLabel filesIndexedNameLabel;
private javax.swing.JLabel filesIndexedValLabel;
private javax.swing.JList jList1;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JTable keywordTable;
private javax.swing.JLabel listLabel;
private javax.swing.JButton loadListButton;
private javax.swing.JButton saveListButton;
private javax.swing.JButton searchButton;
private javax.swing.JLabel titleLabel;
// End of variables declaration//GEN-END:variables
@Override
public void componentOpened() {
// TODO add custom code on component opening
@ -265,7 +343,7 @@ public final class KeywordSearchListTopComponent extends TopComponent implements
String version = p.getProperty("version");
// TODO read your settings according to their version
}
@Override
public boolean isMultiwordQuery() {
return true;
@ -281,6 +359,20 @@ public final class KeywordSearchListTopComponent extends TopComponent implements
return null;
}
@Override
public Map<String,Boolean> getQueryList() {
List<String> selected = getSelectedKeywords();
//filter out blank just in case
Map<String,Boolean> ret = new LinkedHashMap<String,Boolean>();
for (String s : selected) {
if (!s.trim().equals(""))
ret.put(s, false);
}
return ret;
}
@Override
public boolean isLuceneQuerySelected() {
return false;
@ -294,12 +386,124 @@ public final class KeywordSearchListTopComponent extends TopComponent implements
@Override
public void setFilesIndexed(int filesIndexed) {
filesIndexedValLabel.setText(Integer.toString(filesIndexed));
if (filesIndexed == 0) {
if (filesIndexed == 0) {
searchButton.setEnabled(false);
} else {
searchButton.setEnabled(true);
}
}
public List<String> getAllKeywords() {
return tableModel.getAllKeywords();
}
public List<String> getSelectedKeywords() {
return tableModel.getSelectedKeywords();
}
private boolean keywordExists(String keyword) {
return tableModel.keywordExists(keyword);
}
class KeywordTableModel extends AbstractTableModel {
//data
private List<TableEntry> keywordData = new ArrayList<TableEntry>();
@Override
public int getColumnCount() {
return 2;
}
@Override
public int getRowCount() {
return keywordData.size();
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
Object ret = null;
switch (columnIndex) {
case 0:
ret = (Object) keywordData.get(rowIndex).keyword;
break;
case 1:
ret = (Object) keywordData.get(rowIndex).isActive;
break;
default:
logger.log(Level.SEVERE, "Invalid table column index: " + columnIndex);
break;
}
return ret;
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return columnIndex == 1 ? true : false;
}
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
if (columnIndex == 1) {
keywordData.get(rowIndex).isActive = (Boolean) aValue;
}
}
@Override
public Class getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
List<String> getAllKeywords() {
List<String> ret = new ArrayList<String>();
for (TableEntry e : keywordData) {
ret.add(e.keyword);
}
return ret;
}
List<String> getSelectedKeywords() {
List<String> ret = new ArrayList<String>();
for (TableEntry e : keywordData) {
if (e.isActive) {
ret.add(e.keyword);
}
}
return ret;
}
boolean keywordExists(String keyword) {
List<String> all = getAllKeywords();
return all.contains(keyword);
}
void addKeyword(String keyword) {
keywordData.add(0, new TableEntry(keyword));
this.fireTableRowsInserted(keywordData.size() - 1, keywordData.size());
}
void initEmpty() {
for (int i = 0; i<20; ++i) {
keywordData.add(0, new TableEntry("", false));
}
this.fireTableDataChanged();
}
class TableEntry {
String keyword;
Boolean isActive;
TableEntry(String keyword, Boolean isActive) {
this.keyword = keyword;
this.isActive = isActive;
}
TableEntry(String keyword) {
this.keyword = keyword;
this.isActive = true;
}
}
}
}

View File

@ -1,7 +1,6 @@
<?xml version="1.1" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>

View File

@ -19,6 +19,7 @@
package org.sleuthkit.autopsy.keywordsearch;
import java.awt.event.ActionListener;
import java.util.Map;
import java.util.logging.Logger;
import org.openide.windows.TopComponent;
@ -152,6 +153,11 @@ public class KeywordSearchSimpleTopComponent extends TopComponent implements Key
return queryTextArea.getText();
}
@Override
public Map<String,Boolean> getQueryList() {
return null;
}
@Override
public boolean isLuceneQuerySelected() {
return !chRegex.isSelected();

View File

@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.keywordsearch;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.solr.client.solrj.SolrServerException;
@ -139,6 +140,17 @@ public final class KeywordSearchTabsTopComponent extends TopComponent implements
return selected.getQueryText();
}
@Override
public Map<String, Boolean> getQueryList() {
KeywordSearchTopComponentInterface selected = (KeywordSearchTopComponentInterface) tabs.getSelectedComponent();
if (selected == null) {
return null;
}
return selected.getQueryList();
}
@Override
public boolean isLuceneQuerySelected() {
KeywordSearchTopComponentInterface selected = (KeywordSearchTopComponentInterface) tabs.getSelectedComponent();

View File

@ -19,6 +19,7 @@
package org.sleuthkit.autopsy.keywordsearch;
import java.awt.event.ActionListener;
import java.util.Map;
/**
@ -31,6 +32,7 @@ public interface KeywordSearchTopComponentInterface {
boolean isLuceneQuerySelected();
boolean isRegexQuerySelected();
String getQueryText();
Map<String, Boolean> getQueryList();
void setFilesIndexed(int filesIndexed);
void addSearchButtonListener(ActionListener l);

View File

@ -19,16 +19,20 @@
package org.sleuthkit.autopsy.keywordsearch;
import java.awt.Component;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import org.sleuthkit.datamodel.Directory;
import org.sleuthkit.datamodel.FsContent;
import org.sleuthkit.datamodel.TskException;
public class KeywordSearchUtil {
public enum DIALOG_MESSAGE_TYPE {ERROR, WARN, INFO};
private static final Logger logger = Logger.getLogger(KeywordSearchUtil.class.getName());
public static String buildDirName(FsContent f) {
@ -65,4 +69,20 @@ public class KeywordSearchUtil {
}
return queryEscaped;
}
public static void displayDialog(final String title, final String message, final DIALOG_MESSAGE_TYPE type) {
int messageType;
if (type == DIALOG_MESSAGE_TYPE.ERROR)
messageType = JOptionPane.ERROR_MESSAGE;
else if (type == DIALOG_MESSAGE_TYPE.WARN)
messageType = JOptionPane.WARNING_MESSAGE;
else messageType = JOptionPane.INFORMATION_MESSAGE;
final Component parentComponent = null; // Use default window frame.
JOptionPane.showMessageDialog(
parentComponent,
message,
title,
messageType);
}
}

View File

@ -153,7 +153,7 @@ public class TermComponentQuery implements KeywordSearchQuery {
*/
@Override
public List<FsContent> performQuery() {
List<FsContent> results = new ArrayList();
List<FsContent> results = new ArrayList<FsContent>();
final SolrQuery q = createQuery();
terms = executeQuery(q);