(TSK-283) Keyword search should not be enabled if there is nothing in the index

This commit is contained in:
unknown 2011-12-09 10:48:39 -05:00
parent ef9e96721f
commit 71fafdb6bd
7 changed files with 199 additions and 22 deletions

View File

@ -3,3 +3,7 @@ IndexProgressPanel.statusText.text=Status text
IndexProgressPanel.cancelButton.text=Cancel
KeywordSearchTopComponent.searchButton.text=Search
KeywordSearchTopComponent.queryLabel.text=Solr query:
KeywordSearchTopComponent.filesIndexedNameLabel.text=Files indexed:
KeywordSearchTopComponent.filesIndexedValLabel.text=-
KeywordSearchTopComponent.filesIndexedNameLabel.AccessibleContext.accessibleName=Files indexed:
KeywordSearchTopComponent.filesIndexedValLabel.AccessibleContext.accessibleName=-

View File

@ -35,6 +35,7 @@ import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.SwingWorker;
import org.apache.solr.client.solrj.SolrServerException;
import org.sleuthkit.autopsy.keywordsearch.Ingester.IngesterException;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.FsContent;
@ -44,13 +45,12 @@ import org.sleuthkit.datamodel.FsContent;
* children to the Solr index.
*/
public class IndexContentFilesAction extends AbstractAction {
private static final Logger logger = Logger.getLogger(IndexContentFilesAction.class.getName());
private Content c;
private String name;
private Server.Core solrCore;
/**
* New action
* @param c source Content object to get files from
@ -59,7 +59,7 @@ public class IndexContentFilesAction extends AbstractAction {
public IndexContentFilesAction(Content c, String name) {
this(c, name, KeywordSearch.getServer().getCore());
}
IndexContentFilesAction(Content c, String name, Server.Core solrCore) {
super("Index files...");
this.c = c;
@ -69,7 +69,7 @@ public class IndexContentFilesAction extends AbstractAction {
@Override
public void actionPerformed(ActionEvent e) {
// create the popUp window to display progress
String title = "Indexing files in " + name;
@ -93,7 +93,7 @@ public class IndexContentFilesAction extends AbstractAction {
int fileCount = files.size();
int finishedFiles = 0;
int problemFiles = 0;
for (FsContent f : files) {
if (isCancelled()) {
return problemFiles;
@ -113,13 +113,20 @@ public class IndexContentFilesAction extends AbstractAction {
ingester.commit();
try {
final int numIndexedFiles = KeywordSearch.getServer().getCore().queryNumIndexedFiles();
KeywordSearch.changeSupport.firePropertyChange(KeywordSearch.NUM_FILES_CHANGE_EVT, null, new Integer(numIndexedFiles));
} catch (SolrServerException se) {
logger.log(Level.SEVERE, "Error executing Solr query, " + se.getMessage());
}
return problemFiles;
}
@Override
protected void done() {
int problemFiles = 0;
try {
if (!this.isCancelled()) {
problemFiles = get();
@ -133,7 +140,7 @@ public class IndexContentFilesAction extends AbstractAction {
} finally {
popUpWindow.setVisible(false);
popUpWindow.dispose();
// notify user if there were problem files
if (problemFiles > 0) {
displayProblemFilesDialog(problemFiles);
@ -187,8 +194,7 @@ public class IndexContentFilesAction extends AbstractAction {
// display the window
popUpWindow.setVisible(true);
}
private void displayProblemFilesDialog(int problemFiles) {
final Component parentComponent = null; // Use default window frame.
final String message = "Had trouble indexing " + problemFiles + " of the files. See the log for details.";

View File

@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.keywordsearch;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import org.sleuthkit.autopsy.casemodule.Case;
/**
@ -30,6 +31,10 @@ class KeywordSearch {
private static final String BASE_URL = "http://localhost:8983/solr/";
private static final Server SERVER = new Server(BASE_URL);
public static final String NUM_FILES_CHANGE_EVT = "NUM_FILES_CHANGE_EVT";
static PropertyChangeSupport changeSupport = new PropertyChangeSupport(KeywordSearch.class);
static Server getServer() {
return SERVER;
}

View File

@ -22,6 +22,7 @@ import java.awt.Cursor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
@ -64,6 +65,8 @@ public class KeywordSearchDataExplorer implements DataExplorer {
}
}
});
KeywordSearch.changeSupport.addPropertyChangeListener(KeywordSearch.NUM_FILES_CHANGE_EVT, new IndexChangeListener());
}
private synchronized void setTheInstance() {
@ -139,4 +142,28 @@ public class KeywordSearchDataExplorer implements DataExplorer {
@Override
public void propertyChange(PropertyChangeEvent evt) {
}
class IndexChangeListener implements PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent evt) {
String changed = evt.getPropertyName();
//Object oldValue = evt.getOldValue();
Object newValue = evt.getNewValue();
if (newValue != null) {
if (changed.equals(KeywordSearch.NUM_FILES_CHANGE_EVT)) {
int newFilesIndexed = ((Integer) newValue).intValue();
tc.setFilesIndexed(newFilesIndexed);
} else {
String msg = "Unsupported change event: " + changed;
throw new UnsupportedOperationException(msg);
}
}
}
}
}

View File

@ -20,8 +20,13 @@
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="queryLabel" min="-2" max="-2" attributes="0"/>
<Component id="jScrollPane1" alignment="0" pref="302" max="32767" attributes="0"/>
<Component id="jScrollPane1" alignment="0" pref="599" max="32767" 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 max="-2" attributes="0"/>
<Component id="filesIndexedValLabel" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
@ -36,7 +41,12 @@
<Component id="jScrollPane1" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="searchButton" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="132" max="32767" attributes="0"/>
<EmptySpace type="unrelated" 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 pref="107" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -71,5 +81,29 @@
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="filesIndexedNameLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="KeywordSearchTopComponent.filesIndexedNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<AccessibilityProperties>
<Property name="AccessibleContext.accessibleName" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="KeywordSearchTopComponent.filesIndexedNameLabel.AccessibleContext.accessibleName" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</AccessibilityProperties>
</Component>
<Component class="javax.swing.JLabel" name="filesIndexedValLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="KeywordSearchTopComponent.filesIndexedValLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<AccessibilityProperties>
<Property name="AccessibleContext.accessibleName" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="KeywordSearchTopComponent.filesIndexedValLabel.AccessibleContext.accessibleName" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</AccessibilityProperties>
</Component>
</SubComponents>
</Form>

View File

@ -19,16 +19,30 @@
package org.sleuthkit.autopsy.keywordsearch;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.solr.client.solrj.SolrServerException;
import org.openide.windows.TopComponent;
public class KeywordSearchTopComponent extends TopComponent {
private Logger logger = Logger.getLogger(KeywordSearchTopComponent.class.getName());
private PropertyChangeListener serverChangeListener;
/** Creates new form KeywordSearchTopComponent */
public KeywordSearchTopComponent() {
initComponents();
setName("Keyword Search");
searchButton.setEnabled(false);
putClientProperty(TopComponent.PROP_CLOSING_DISABLED, Boolean.TRUE);
//register with server Actions
serverChangeListener = new KeywordSearchServerListener();
KeywordSearch.getServer().addServerActionListener(serverChangeListener);
}
/** This method is called from within the constructor to
@ -44,6 +58,8 @@ public class KeywordSearchTopComponent extends TopComponent {
queryTextArea = new javax.swing.JTextArea();
searchButton = new javax.swing.JButton();
queryLabel = new javax.swing.JLabel();
filesIndexedNameLabel = new javax.swing.JLabel();
filesIndexedValLabel = new javax.swing.JLabel();
queryTextArea.setColumns(20);
queryTextArea.setRows(5);
@ -53,21 +69,24 @@ public class KeywordSearchTopComponent extends TopComponent {
queryLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchTopComponent.class, "KeywordSearchTopComponent.queryLabel.text")); // NOI18N
filesIndexedNameLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchTopComponent.class, "KeywordSearchTopComponent.filesIndexedNameLabel.text")); // NOI18N
filesIndexedValLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchTopComponent.class, "KeywordSearchTopComponent.filesIndexedValLabel.text")); // NOI18N
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()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(queryLabel)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 599, Short.MAX_VALUE)
.addComponent(searchButton)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(queryLabel))
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 302, Short.MAX_VALUE))
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(searchButton)))
.addComponent(filesIndexedNameLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(filesIndexedValLabel)))
.addContainerGap())
);
layout.setVerticalGroup(
@ -79,10 +98,19 @@ public class KeywordSearchTopComponent extends TopComponent {
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(searchButton)
.addContainerGap(132, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(filesIndexedNameLabel)
.addComponent(filesIndexedValLabel))
.addContainerGap(107, Short.MAX_VALUE))
);
filesIndexedNameLabel.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(KeywordSearchTopComponent.class, "KeywordSearchTopComponent.filesIndexedNameLabel.AccessibleContext.accessibleName")); // NOI18N
filesIndexedValLabel.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(KeywordSearchTopComponent.class, "KeywordSearchTopComponent.filesIndexedValLabel.AccessibleContext.accessibleName")); // NOI18N
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JLabel filesIndexedNameLabel;
private javax.swing.JLabel filesIndexedValLabel;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JLabel queryLabel;
private javax.swing.JTextArea queryTextArea;
@ -96,7 +124,7 @@ public class KeywordSearchTopComponent extends TopComponent {
String getQueryText() {
return queryTextArea.getText();
}
/**
* Overwrite when you want to change default persistence type. Default
* persistence type is PERSISTENCE_ALWAYS
@ -107,4 +135,43 @@ public class KeywordSearchTopComponent extends TopComponent {
public int getPersistenceType() {
return TopComponent.PERSISTENCE_NEVER;
}
public void setFilesIndexed(int filesIndexed) {
filesIndexedValLabel.setText(Integer.toString(filesIndexed));
if (filesIndexed == 0) {
searchButton.setEnabled(false);
} else {
searchButton.setEnabled(true);
}
}
class KeywordSearchServerListener implements PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent evt) {
String eventType = evt.getPropertyName();
if (eventType.equals(Server.CORE_EVT)) {
final Server.CORE_EVT_STATES state = (Server.CORE_EVT_STATES) evt.getNewValue();
switch (state) {
case STARTED:
try {
final int numIndexedFiles = KeywordSearch.getServer().getCore().queryNumIndexedFiles();
KeywordSearch.changeSupport.firePropertyChange(KeywordSearch.NUM_FILES_CHANGE_EVT, null, new Integer(numIndexedFiles));
} catch (SolrServerException se) {
logger.log(Level.SEVERE, "Error executing Solr query, " + se.getMessage());
}
break;
case STOPPED:
break;
default:
}
}
}
}
}

View File

@ -18,6 +18,8 @@
*/
package org.sleuthkit.autopsy.keywordsearch;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
@ -28,6 +30,7 @@ import java.net.MalformedURLException;
import java.net.SocketException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.AbstractAction;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.SolrServerException;
@ -47,10 +50,13 @@ class Server {
private static final String DEFAULT_CORE_NAME = "coreCase";
// TODO: DEFAULT_CORE_NAME needs to be replaced with unique names to support multiple open cases
public static final String CORE_EVT = "CORE_EVT";
public enum CORE_EVT_STATES { STOPPED, STARTED };
private CommonsHttpSolrServer solr;
private String instanceDir;
private File solrFolder;
private ServerAction serverAction;
/**
* New instance for the server at the given URL
@ -63,10 +69,14 @@ class Server {
throw new RuntimeException(ex);
}
serverAction = new ServerAction();
solrFolder = InstalledFileLocator.getDefault().locate("solr", Server.class.getPackage().getName(), false);
instanceDir = solrFolder.getAbsolutePath() + File.separator + "solr";
}
public void addServerActionListener(PropertyChangeListener l) {
serverAction.addPropertyChangeListener(l);
}
/**
* Helper threads to handle stderr/stdout from Solr process
@ -79,6 +89,7 @@ class Server {
this.stream = stream;
}
@Override
public void run() {
InputStreamReader isr = new InputStreamReader(stream);
BufferedReader br = new BufferedReader(isr);
@ -174,6 +185,7 @@ class Server {
throw new RuntimeException("Already an open Core!");
}
currentCore = openCore(Case.getCurrentCase());
serverAction.putValue(CORE_EVT, CORE_EVT_STATES.STARTED);
}
void closeCore() {
@ -182,6 +194,7 @@ class Server {
}
currentCore.close();
currentCore = null;
serverAction.putValue(CORE_EVT, CORE_EVT_STATES.STOPPED);
}
Core getCore() {
@ -269,5 +282,26 @@ class Server {
throw new RuntimeException(ex);
}
}
/**
* Execute query that gets only number of all Solr documents indexed
* without actually returning the documents
* @return int representing number of indexed files
* @throws SolrServerException
*/
public int queryNumIndexedFiles() throws SolrServerException {
SolrQuery q = new SolrQuery("*:*");
q.setRows(0);
return (int)query(q).getResults().getNumFound();
}
}
class ServerAction extends AbstractAction {
@Override
public void actionPerformed(ActionEvent e) {
logger.log(Level.INFO, e.paramString());
}
}
}