diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties
index e3853e4d59..562d4366b1 100644
--- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties
+++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties
@@ -1,6 +1,9 @@
+CTL_KeywordSearchListAction=List
+CTL_KeywordSearchListTopComponent=List
CTL_KeywordSearchTabsTopComponentAction=Keyword Search
CTL_KeywordSearchTabsTopComponentTopComponent=Keyword Search
-HINT_KeywordSearchTabsTopComponentTopComponent=This is a Keyword Search window
+HINT_KeywordSearchListTopComponent=Keyword Search List
+HINT_KeywordSearchTabsTopComponentTopComponent=Keyword Search window
OpenIDE-Module-Name=KeywordSearch
IndexProgressPanel.statusText.text=Status text
IndexProgressPanel.cancelButton.text=Cancel
@@ -17,5 +20,17 @@ KeywordSearchSimpleTopComponent.filesIndexedValLabel.text=-
KeywordSearchSimpleTopComponent.filesIndexedNameLabel.text=Files indexed:
KeywordSearchSimpleTopComponent.queryLabel.text=Query:
KeywordSearchSimpleTopComponent.searchButton.text=Search
-KeywordSearchSimpleTopComponent.regexQRadioButton.text=RegEx
-KeywordSearchSimpleTopComponent.luceneQRadioButton.text=Lucene
+KeywordSearchListTopComponent.searchButton.text=Search
+KeywordSearchListTopComponent.filesIndexedNameLabel.text=Files indexed:
+KeywordSearchListTopComponent.filesIndexedValLabel.text=-
+KeywordSearchListTopComponent.titleLabel.text=Search for or load a saved list of keywords
+KeywordSearchListTopComponent.listLabel.text=Current list of keywords:
+KeywordSearchListTopComponent.addWordButton.text=Add
+KeywordSearchListTopComponent.loadListButton.text=Load
+KeywordSearchListTopComponent.addWordField.text=
+KeywordSearchListTopComponent.saveListButton.text=Save
+KeywordSearchListTopComponent.chLiteralWord.text=Literal
+KeywordSearchListTopComponent.addWordLabel.text=Add a new word:
+KeywordSearchListTopComponent.deleteWordButton.text=Delete
+KeywordSearchListTopComponent.deleteAllWordsButton.text=Delete All
+KeywordSearchSimpleTopComponent.chRegex.text=RegEx
diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchDataExplorer.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchDataExplorer.java
index c6aef55e82..c6728a4fa0 100644
--- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchDataExplorer.java
+++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchDataExplorer.java
@@ -95,7 +95,7 @@ public class KeywordSearchDataExplorer implements DataExplorer {
* @param solrQuery
*/
private void searchRegexQuery(String regexQuery) {
- RegexQuery rq = new RegexQuery(regexQuery);
+ TermComponentQuery rq = new TermComponentQuery(regexQuery);
if (rq.validate()) {
rq.execute();
} else {
diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListTopComponent.form b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListTopComponent.form
new file mode 100644
index 0000000000..385c224ce0
--- /dev/null
+++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListTopComponent.form
@@ -0,0 +1,229 @@
+
+
+
diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListTopComponent.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListTopComponent.java
new file mode 100644
index 0000000000..c8d6836fdd
--- /dev/null
+++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListTopComponent.java
@@ -0,0 +1,305 @@
+/*
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2011 Basis Technology Corp.
+ * Contact: carrier sleuthkit org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * 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.logging.Logger;
+import org.openide.util.NbBundle;
+import org.openide.windows.TopComponent;
+import org.netbeans.api.settings.ConvertAsProperties;
+import org.openide.awt.ActionID;
+import org.openide.awt.ActionReference;
+
+/**
+ * Top component which displays something.
+ */
+@ConvertAsProperties(dtd = "-//org.sleuthkit.autopsy.keywordsearch//KeywordSearchList//EN",
+autostore = false)
+@TopComponent.Description(preferredID = "KeywordSearchListTopComponent",
+//iconBase="SET/PATH/TO/ICON/HERE",
+persistenceType = TopComponent.PERSISTENCE_NEVER)
+@TopComponent.Registration(mode = "output", openAtStartup = false)
+@ActionID(category = "Window", id = "org.sleuthkit.autopsy.keywordsearch.KeywordSearchListTopComponent")
+@ActionReference(path = "Menu/Window" /*, position = 333 */)
+@TopComponent.OpenActionRegistration(displayName = "#CTL_KeywordSearchListAction",
+preferredID = "KeywordSearchListTopComponent")
+public final class KeywordSearchListTopComponent extends TopComponent implements KeywordSearchTopComponentInterface {
+
+ private Logger logger = Logger.getLogger(KeywordSearchListTopComponent.class.getName());
+
+ public KeywordSearchListTopComponent() {
+ 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)");
+ 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)");
+
+ }
+
+ /** This method is called from within the constructor to
+ * initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is
+ * always regenerated by the Form Editor.
+ */
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ 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();
+ addWordLabel = new javax.swing.JLabel();
+ addWordButton = new javax.swing.JButton();
+ loadListButton = new javax.swing.JButton();
+ deleteWordButton = new javax.swing.JButton();
+ deleteAllWordsButton = new javax.swing.JButton();
+ saveListButton = new javax.swing.JButton();
+ chLiteralWord = new javax.swing.JCheckBox();
+
+ org.openide.awt.Mnemonics.setLocalizedText(searchButton, org.openide.util.NbBundle.getMessage(KeywordSearchListTopComponent.class, "KeywordSearchListTopComponent.searchButton.text")); // NOI18N
+ searchButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ searchButtonActionPerformed(evt);
+ }
+ });
+
+ org.openide.awt.Mnemonics.setLocalizedText(filesIndexedNameLabel, org.openide.util.NbBundle.getMessage(KeywordSearchListTopComponent.class, "KeywordSearchListTopComponent.filesIndexedNameLabel.text")); // NOI18N
+
+ 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
+
+ addWordField.setText(org.openide.util.NbBundle.getMessage(KeywordSearchListTopComponent.class, "KeywordSearchListTopComponent.addWordField.text")); // NOI18N
+
+ org.openide.awt.Mnemonics.setLocalizedText(addWordLabel, org.openide.util.NbBundle.getMessage(KeywordSearchListTopComponent.class, "KeywordSearchListTopComponent.addWordLabel.text")); // NOI18N
+
+ org.openide.awt.Mnemonics.setLocalizedText(addWordButton, org.openide.util.NbBundle.getMessage(KeywordSearchListTopComponent.class, "KeywordSearchListTopComponent.addWordButton.text")); // NOI18N
+ addWordButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ addWordButtonActionPerformed(evt);
+ }
+ });
+
+ 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
+
+ org.openide.awt.Mnemonics.setLocalizedText(deleteAllWordsButton, org.openide.util.NbBundle.getMessage(KeywordSearchListTopComponent.class, "KeywordSearchListTopComponent.deleteAllWordsButton.text")); // NOI18N
+
+ org.openide.awt.Mnemonics.setLocalizedText(saveListButton, org.openide.util.NbBundle.getMessage(KeywordSearchListTopComponent.class, "KeywordSearchListTopComponent.saveListButton.text")); // NOI18N
+ saveListButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ saveListButtonActionPerformed(evt);
+ }
+ });
+
+ org.openide.awt.Mnemonics.setLocalizedText(chLiteralWord, org.openide.util.NbBundle.getMessage(KeywordSearchListTopComponent.class, "KeywordSearchListTopComponent.chLiteralWord.text")); // NOI18N
+ chLiteralWord.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ chLiteralWordActionPerformed(evt);
+ }
+ });
+
+ 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)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(filesIndexedNameLabel)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(filesIndexedValLabel))
+ .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))))
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(titleLabel)
+ .addGap(18, 18, 18)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(loadListButton)
+ .addComponent(saveListButton))
+ .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)
+ .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)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(deleteWordButton)
+ .addComponent(deleteAllWordsButton))
+ .addGap(30, 30, 30)
+ .addComponent(searchButton)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(filesIndexedNameLabel)
+ .addComponent(filesIndexedValLabel))
+ .addGap(42, 42, 42))
+ );
+ }// //GEN-END:initComponents
+
+ private void searchButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_searchButtonActionPerformed
+ // TODO add your handling code here:
+ }//GEN-LAST:event_searchButtonActionPerformed
+
+ private void addWordButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addWordButtonActionPerformed
+ // TODO add your handling code here:
+ }//GEN-LAST:event_addWordButtonActionPerformed
+
+ private void saveListButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveListButtonActionPerformed
+ // TODO add your handling code here:
+ }//GEN-LAST:event_saveListButtonActionPerformed
+
+ private void chLiteralWordActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chLiteralWordActionPerformed
+ // TODO add your handling code here:
+ }//GEN-LAST:event_chLiteralWordActionPerformed
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JButton addWordButton;
+ private javax.swing.JTextField addWordField;
+ private javax.swing.JLabel addWordLabel;
+ private javax.swing.JCheckBox chLiteralWord;
+ private javax.swing.JButton deleteAllWordsButton;
+ 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.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
+ }
+
+ @Override
+ public void componentClosed() {
+ // TODO add custom code on component closing
+ }
+
+ void writeProperties(java.util.Properties p) {
+ // better to version settings since initial version as advocated at
+ // http://wiki.apidesign.org/wiki/PropertyFiles
+ p.setProperty("version", "1.0");
+ // TODO store your settings
+ }
+
+ void readProperties(java.util.Properties p) {
+ String version = p.getProperty("version");
+ // TODO read your settings according to their version
+ }
+
+ @Override
+ public boolean isMultiwordQuery() {
+ return true;
+ }
+
+ @Override
+ public void addSearchButtonListener(ActionListener l) {
+ searchButton.addActionListener(l);
+ }
+
+ @Override
+ public String getQueryText() {
+ return null;
+ }
+
+ @Override
+ public boolean isLuceneQuerySelected() {
+ return false;
+ }
+
+ @Override
+ public boolean isRegexQuerySelected() {
+ return true;
+ }
+
+ @Override
+ public void setFilesIndexed(int filesIndexed) {
+ filesIndexedValLabel.setText(Integer.toString(filesIndexed));
+ if (filesIndexed == 0) {
+ searchButton.setEnabled(false);
+ } else {
+ searchButton.setEnabled(true);
+ }
+ }
+
+
+}
diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchQuery.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchQuery.java
index 17f11fbac2..7839c7706f 100644
--- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchQuery.java
+++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchQuery.java
@@ -18,6 +18,9 @@
*/
package org.sleuthkit.autopsy.keywordsearch;
+import java.util.List;
+import org.sleuthkit.datamodel.FsContent;
+
public interface KeywordSearchQuery {
/**
@@ -26,8 +29,23 @@ public interface KeywordSearchQuery {
*/
public boolean validate();
+
/**
- * execute the query
+ * execute query and return results without publishing them
+ * @return
+ */
+ public List performQuery();
+
+
+ /**
+ * execute the query and publish results
*/
public void execute();
+
+ /**
+ * escape the query string and use the escaped string in the query
+ */
+ public void escape();
+
+
}
diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/RegexQuery.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java
similarity index 50%
rename from KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/RegexQuery.java
rename to KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java
index 6798340925..cd7f725644 100644
--- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/RegexQuery.java
+++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchResultFactory.java
@@ -21,31 +21,20 @@ package org.sleuthkit.autopsy.keywordsearch;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
-import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
-import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import java.util.regex.PatternSyntaxException;
-import javax.swing.SwingWorker;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
-import org.apache.solr.client.solrj.response.TermsResponse;
-import org.apache.solr.client.solrj.response.TermsResponse.Term;
-import org.netbeans.api.progress.ProgressHandle;
-import org.netbeans.api.progress.ProgressHandleFactory;
-import org.openide.nodes.AbstractNode;
import org.openide.nodes.ChildFactory;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
-import org.openide.windows.TopComponent;
-import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent;
import org.sleuthkit.autopsy.datamodel.AbstractFsContentNode;
import org.sleuthkit.autopsy.datamodel.AbstractFsContentNode.FsContentPropertyType;
import org.sleuthkit.autopsy.datamodel.KeyValueNode;
@@ -54,182 +43,97 @@ import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.File;
import org.sleuthkit.datamodel.FsContent;
-public class RegexQuery implements KeywordSearchQuery {
+/**
+ *
+ * factory responsible for assembling nodes in the right way
+ * and performing lazy queries as needed
+ */
+public class KeywordSearchResultFactory extends ChildFactory {
+
+ public enum Presentation {
+
+ COLLAPSE, STRUCTURE
+ };
- private static final int TERMS_UNLIMITED = -1;
- //corresponds to field in Solr schema, analyzed with white-space tokenizer only
- private static final String TERMS_SEARCH_FIELD = "content_ws";
- private static final String TERMS_HANDLER = "/terms";
- private static final int TERMS_TIMEOUT = 90 * 1000; //in ms
- private String regexQuery;
- private static Logger logger = Logger.getLogger(RegexQuery.class.getName());
-
//common properties (superset of all Node properties) to be displayed as columns
//these are merged with FsContentPropertyType defined properties
- private static enum CommonPropertyTypes {
+ public static enum CommonPropertyTypes {
+
QUERY {
+
@Override
public String toString() {
return "Query";
}
- },
+ },
MATCH {
+
@Override
public String toString() {
return "Match";
}
- },
- /* MATCH_RANK {
- @Override
- public String toString() {
- return "Match Rank";
- }
- },*/
+ },
}
-
+ private Presentation presentation;
+ private Collection queries;
+ private Collection things;
+ private static final Logger logger = Logger.getLogger(KeywordSearchResultFactory.class.getName());
- public RegexQuery(String query) {
- this.regexQuery = query;
+ KeywordSearchResultFactory(Collection queries, Collection things, Presentation presentation) {
+ this.queries = queries;
+ this.things = things;
+ this.presentation = presentation;
}
- @Override
- public boolean validate() {
- boolean valid = true;
- try {
- Pattern.compile(regexQuery);
- } catch (PatternSyntaxException ex1) {
- valid = false;
- } catch (IllegalArgumentException ex2) {
- valid = false;
- }
- return valid;
+ KeywordSearchResultFactory(String query, Collection things, Presentation presentation) {
+ queries = new ArrayList();
+ queries.add(query);
+ this.presentation = presentation;
+ this.things = things;
}
- @Override
- public void execute() {
-
- final SolrQuery q = new SolrQuery();
- q.setQueryType(TERMS_HANDLER);
- q.setTerms(true);
- q.setTermsLimit(TERMS_UNLIMITED);
- q.setTermsRegexFlag("case_insensitive");
- //q.setTermsLimit(200);
- //q.setTermsRegexFlag(regexFlag);
- //q.setTermsRaw(true);
- q.setTermsRegex(regexQuery);
- q.addTermsField(TERMS_SEARCH_FIELD);
- q.setTimeAllowed(TERMS_TIMEOUT);
-
- logger.log(Level.INFO, "Executing TermsComponent query: " + q.toString());
-
- final SwingWorker worker = new RegexQueryWorker(q);
- worker.execute();
- }
-
- /**
- * map Terms to generic Nodes with key/value pairs properties
- * @param terms
- */
- private void publishNodes(List terms) {
-
- Collection things = new ArrayList();
-
- Iterator it = terms.iterator();
- int termID = 0;
- //long totalMatches = 0;
- while (it.hasNext()) {
- Term term = it.next();
- Map kvs = new LinkedHashMap();
- long matches = term.getFrequency();
- final String match = term.getTerm();
- setCommonProperty(kvs, CommonPropertyTypes.MATCH, match);
- //setCommonProperty(kvs, CommonPropertyTypes.MATCH_RANK, Long.toString(matches));
- things.add(new KeyValueThing(match, kvs, ++termID));
- //totalMatches += matches;
- }
-
- Node rootNode = null;
- if (things.size() > 0) {
- Children childThingNodes =
- Children.create(new RegexResultQueryChildFactory(regexQuery, things), true);
-
- rootNode = new AbstractNode(childThingNodes);
- } else {
- rootNode = Node.EMPTY;
- }
-
- final String pathText = "RegEx query";
- // String pathText = "RegEx query: " + regexQuery
- //+ " Files with exact matches: " + Long.toString(totalMatches) + " (also listing approximate matches)";
-
- TopComponent searchResultWin = DataResultTopComponent.createInstance("Keyword search", pathText, rootNode, things.size());
- searchResultWin.requestActive(); // make it the active top component
-
- }
-
/**
* call this at least for the parent Node, to make sure all common
* properties are displayed as columns (since we are doing lazy child Node load
* we need to preinitialize properties when sending parent Node)
* @param toSet property set map for a Node
*/
- private static void initCommonProperties(Map toSet) {
- CommonPropertyTypes [] commonTypes = CommonPropertyTypes.values();
+ public static void initCommonProperties(Map toSet) {
+ CommonPropertyTypes[] commonTypes = CommonPropertyTypes.values();
final int COMMON_PROPS_LEN = commonTypes.length;
- for (int i = 0; i< COMMON_PROPS_LEN; ++i) {
+ for (int i = 0; i < COMMON_PROPS_LEN; ++i) {
toSet.put(commonTypes[i].toString(), "");
}
-
- FsContentPropertyType [] fsTypes = FsContentPropertyType.values();
+
+ FsContentPropertyType[] fsTypes = FsContentPropertyType.values();
final int FS_PROPS_LEN = fsTypes.length;
- for (int i = 0; i< FS_PROPS_LEN; ++i) {
+ for (int i = 0; i < FS_PROPS_LEN; ++i) {
toSet.put(fsTypes[i].toString(), "");
}
}
-
- private static void setCommonProperty(Map toSet, CommonPropertyTypes type, String value) {
+
+ public static void setCommonProperty(Map toSet, CommonPropertyTypes type, String value) {
final String typeStr = type.toString();
toSet.put(typeStr, value);
}
-
- /**
- * factory produces top level result nodes showing query used
- */
- class RegexResultQueryChildFactory extends ChildFactory {
- Collection queries;
- Collection things;
-
-
- RegexResultQueryChildFactory(Collectionqueries, Collection things) {
- this.queries = queries;
- this.things = things;
- }
-
- RegexResultQueryChildFactory(String query, Collection things) {
- queries = new ArrayList();
- queries.add(query);
- this.things = things;
+ @Override
+ protected boolean createKeys(List toPopulate) {
+ int id = 0;
+ for (String query : queries) {
+ Map map = new LinkedHashMap();
+ initCommonProperties(map);
+ setCommonProperty(map, CommonPropertyTypes.QUERY, query);
+ toPopulate.add(new KeyValueThing(query, map, ++id));
}
- @Override
- protected boolean createKeys(List toPopulate) {
- int id = 0;
- for (String query : queries) {
- Map map = new LinkedHashMap();
- initCommonProperties(map);
- setCommonProperty(map, CommonPropertyTypes.QUERY, query);
- toPopulate.add(new KeyValueThing(query, map, ++id));
- }
-
- return true;
- }
+ return true;
+ }
- @Override
- protected Node createNodeForKey(KeyValueThing thing) {
- return new KeyValueNode(thing, Children.create(new RegexResultChildFactory(things), true));
- }
+ @Override
+ protected Node createNodeForKey(KeyValueThing thing) {
+ return new KeyValueNode(thing, Children.create(new RegexResultChildFactory(things), true));
}
/**
@@ -273,7 +177,7 @@ public class RegexQuery implements KeywordSearchQuery {
//use Lucene query to get files with regular expression match result
final String keywordQuery = thing.getName();
LuceneQuery filesQuery = new LuceneQuery(keywordQuery);
- List matches = filesQuery.doQuery();
+ List matches = filesQuery.performQuery();
//get unique match result files
Set uniqueMatches = new TreeSet(new Comparator() {
@@ -287,15 +191,14 @@ public class RegexQuery implements KeywordSearchQuery {
uniqueMatches.addAll(matches);
int resID = 0;
- for (FsContent f : uniqueMatches) {
+ for (FsContent f : uniqueMatches) {
Map resMap = new LinkedHashMap();
- AbstractFsContentNode.fillPropertyMap(resMap, (File)f);
+ AbstractFsContentNode.fillPropertyMap(resMap, (File) f);
toPopulate.add(new KeyValueThingContent(f.getName(), resMap, ++resID, f, keywordQuery));
}
return true;
}
-
@Override
protected Node createNodeForKey(KeyValueThing thing) {
@@ -309,7 +212,8 @@ public class RegexQuery implements KeywordSearchQuery {
//TODO option in GUI to include approximate matches (faster)
boolean matchFound = false;
if (contentStr != null) {//if not null, some error getting from Solr, handle it by not filtering out
- Pattern p = Pattern.compile(regexQuery, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
+ final String keywordQuery = thing.getName();
+ Pattern p = Pattern.compile(keywordQuery, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
Matcher m = p.matcher(contentStr);
matchFound = m.find();
}
@@ -362,64 +266,4 @@ public class RegexQuery implements KeywordSearchQuery {
}
}
}
-
- class RegexQueryWorker extends SwingWorker, Void> {
-
- private SolrQuery q;
- private ProgressHandle progress;
-
- RegexQueryWorker(SolrQuery q) {
- this.q = q;
- }
-
- @Override
- protected List doInBackground() throws Exception {
- progress = ProgressHandleFactory.createHandle("RegEx query task");
- progress.start();
- progress.progress("Running RegEx query.");
-
- Server.Core solrCore = KeywordSearch.getServer().getCore();
-
-
- List terms = null;
- try {
- TermsResponse tr = solrCore.queryTerms(q);
- terms = tr.getTerms(TERMS_SEARCH_FIELD);
- } catch (SolrServerException ex) {
- logger.log(Level.SEVERE, "Error executing the regex terms query: " + regexQuery, ex);
- return null; //no need to create result view, just display error dialog
- }
-
- progress.progress("RegEx query completed.");
-
- //debug query
- //StringBuilder sb = new StringBuilder();
- //for (Term t : terms) {
- // sb.append(t.getTerm() + " : " + t.getFrequency() + "\n");
- //}
- //logger.log(Level.INFO, "TermsComponent query result: " + sb.toString());
- //end debug query
-
- return terms;
- }
-
- @Override
- protected void done() {
- if (!this.isCancelled()) {
- try {
- List terms = get();
- publishNodes(terms);
- } catch (InterruptedException e) {
- logger.log(Level.INFO, "Exception while executing regex query,", e);
-
- } catch (ExecutionException e) {
- logger.log(Level.INFO, "Exception while executing regex query,", e);
- } finally {
- progress.finish();
- }
- }
-
-
- }
- }
}
diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchSimpleTopComponent.form b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchSimpleTopComponent.form
index be5325951e..57a7e9b7cd 100644
--- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchSimpleTopComponent.form
+++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchSimpleTopComponent.form
@@ -25,10 +25,8 @@
-
-
-
-
+
+
@@ -48,8 +46,7 @@
-
-
+
@@ -119,20 +116,15 @@
-
-
-
-
-
-
-
-
-
+
-
+
+
+
+
diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchSimpleTopComponent.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchSimpleTopComponent.java
index 364c1e22bc..ef2cab2559 100644
--- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchSimpleTopComponent.java
+++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchSimpleTopComponent.java
@@ -30,8 +30,7 @@ public class KeywordSearchSimpleTopComponent extends TopComponent implements Key
public KeywordSearchSimpleTopComponent() {
initComponents();
setName("Simple");
- buttonGroup1.add(luceneQRadioButton);
- buttonGroup1.add(regexQRadioButton);
+ buttonGroup1.add(chRegex);
searchButton.setEnabled(false);
putClientProperty(TopComponent.PROP_CLOSING_DISABLED, Boolean.TRUE);
@@ -53,8 +52,7 @@ public class KeywordSearchSimpleTopComponent extends TopComponent implements Key
queryLabel = new javax.swing.JLabel();
filesIndexedNameLabel = new javax.swing.JLabel();
filesIndexedValLabel = new javax.swing.JLabel();
- luceneQRadioButton = new javax.swing.JRadioButton();
- regexQRadioButton = new javax.swing.JRadioButton();
+ chRegex = new javax.swing.JCheckBox();
queryTextArea.setColumns(20);
queryTextArea.setRows(5);
@@ -68,10 +66,12 @@ public class KeywordSearchSimpleTopComponent extends TopComponent implements Key
filesIndexedValLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchSimpleTopComponent.class, "KeywordSearchSimpleTopComponent.filesIndexedValLabel.text")); // NOI18N
- luceneQRadioButton.setSelected(true);
- luceneQRadioButton.setText(org.openide.util.NbBundle.getMessage(KeywordSearchSimpleTopComponent.class, "KeywordSearchSimpleTopComponent.luceneQRadioButton.text")); // NOI18N
-
- regexQRadioButton.setText(org.openide.util.NbBundle.getMessage(KeywordSearchSimpleTopComponent.class, "KeywordSearchSimpleTopComponent.regexQRadioButton.text")); // NOI18N
+ chRegex.setText(org.openide.util.NbBundle.getMessage(KeywordSearchSimpleTopComponent.class, "KeywordSearchSimpleTopComponent.chRegex.text")); // NOI18N
+ chRegex.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ chRegexActionPerformed(evt);
+ }
+ });
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
@@ -82,10 +82,8 @@ public class KeywordSearchSimpleTopComponent extends TopComponent implements Key
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(queryLabel)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
- .addComponent(luceneQRadioButton)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
- .addComponent(regexQRadioButton))
+ .addGap(62, 62, 62)
+ .addComponent(chRegex))
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 599, Short.MAX_VALUE)
.addComponent(searchButton)
.addGroup(layout.createSequentialGroup()
@@ -100,8 +98,7 @@ public class KeywordSearchSimpleTopComponent extends TopComponent implements Key
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(queryLabel)
- .addComponent(luceneQRadioButton)
- .addComponent(regexQRadioButton))
+ .addComponent(chRegex))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
@@ -116,15 +113,19 @@ public class KeywordSearchSimpleTopComponent extends TopComponent implements Key
filesIndexedNameLabel.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(KeywordSearchSimpleTopComponent.class, "KeywordSearchTopComponent.filesIndexedNameLabel.AccessibleContext.accessibleName")); // NOI18N
filesIndexedValLabel.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(KeywordSearchSimpleTopComponent.class, "KeywordSearchTopComponent.filesIndexedValLabel.AccessibleContext.accessibleName")); // NOI18N
}// //GEN-END:initComponents
+
+ private void chRegexActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chRegexActionPerformed
+ // TODO add your handling code here:
+ }//GEN-LAST:event_chRegexActionPerformed
+
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.ButtonGroup buttonGroup1;
+ private javax.swing.JCheckBox chRegex;
private javax.swing.JLabel filesIndexedNameLabel;
private javax.swing.JLabel filesIndexedValLabel;
private javax.swing.JScrollPane jScrollPane1;
- private javax.swing.JRadioButton luceneQRadioButton;
private javax.swing.JLabel queryLabel;
private javax.swing.JTextArea queryTextArea;
- private javax.swing.JRadioButton regexQRadioButton;
private javax.swing.JButton searchButton;
// End of variables declaration//GEN-END:variables
@@ -135,6 +136,11 @@ public class KeywordSearchSimpleTopComponent extends TopComponent implements Key
queryTextArea.setText("");
}
+ @Override
+ public boolean isMultiwordQuery() {
+ return false;
+ }
+
@Override
public void addSearchButtonListener(ActionListener l) {
searchButton.addActionListener(l);
@@ -147,12 +153,12 @@ public class KeywordSearchSimpleTopComponent extends TopComponent implements Key
@Override
public boolean isLuceneQuerySelected() {
- return luceneQRadioButton.isSelected();
+ return !chRegex.isSelected();
}
@Override
public boolean isRegexQuerySelected() {
- return regexQRadioButton.isSelected();
+ return chRegex.isSelected();
}
/**
diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchTabsTopComponent.form b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchTabsTopComponent.form
index 4b1b7a5f54..747df8cbdb 100644
--- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchTabsTopComponent.form
+++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchTabsTopComponent.form
@@ -1,6 +1,6 @@
-