diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties
index f22f381760..d55aaa4561 100644
--- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties
+++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties
@@ -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=-
diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/IndexContentFilesAction.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/IndexContentFilesAction.java
index ab9645f61a..8582abc972 100644
--- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/IndexContentFilesAction.java
+++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/IndexContentFilesAction.java
@@ -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.";
diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearch.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearch.java
index 23dab824dc..198c9359a5 100644
--- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearch.java
+++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearch.java
@@ -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;
}
diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchDataExplorer.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchDataExplorer.java
index ba2d16e9ae..cbbfd2b5f0 100644
--- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchDataExplorer.java
+++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchDataExplorer.java
@@ -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);
+}
+ }
+ }
+ }
}
diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchTopComponent.form b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchTopComponent.form
index 58ea055eb3..8033d2ee32 100644
--- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchTopComponent.form
+++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchTopComponent.form
@@ -20,8 +20,13 @@
-
+
+
+
+
+
+
@@ -36,7 +41,12 @@
-
+
+
+
+
+
+
@@ -71,5 +81,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchTopComponent.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchTopComponent.java
index a3f42407b2..a97ca82084 100644
--- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchTopComponent.java
+++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchTopComponent.java
@@ -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
}// //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:
+
+ }
+
+ }
+
+
+ }
+ }
}
diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Server.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Server.java
index 9108a52066..b97d4521d6 100644
--- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Server.java
+++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Server.java
@@ -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());
+ }
+
}
}