19 package org.sleuthkit.autopsy.keywordsearch;
21 import java.io.IOException;
22 import java.lang.reflect.InvocationTargetException;
23 import java.net.InetAddress;
24 import java.util.ArrayList;
25 import java.util.List;
26 import java.util.MissingResourceException;
27 import java.util.logging.Level;
28 import javax.swing.JDialog;
29 import javax.swing.JOptionPane;
30 import javax.swing.SwingUtilities;
31 import org.apache.commons.lang.math.NumberUtils;
32 import org.apache.solr.client.solrj.SolrServerException;
33 import org.apache.solr.client.solrj.impl.HttpSolrServer;
34 import org.openide.util.NbBundle;
35 import org.openide.util.lookup.ServiceProvider;
36 import org.openide.util.lookup.ServiceProviders;
52 @ServiceProviders(value = {
53 @ServiceProvider(service = KeywordSearchService.class),
54 @ServiceProvider(service = AutopsyService.class)}
58 private static final String BAD_IP_ADDRESS_FORMAT =
"ioexception occurred when talking to server";
59 private static final String SERVER_REFUSED_CONNECTION =
"server refused connection";
60 private static final int IS_REACHABLE_TIMEOUT_MS = 1000;
73 if (artifact == null) {
79 if (artifact.getArtifactID() > 0) {
82 final Ingester ingester = Ingester.getDefault();
85 ingester.indexMetaDataOnly(artifact);
86 ingester.indexText(
new ArtifactTextExtractor(), artifact, null);
87 }
catch (Ingester.IngesterException ex) {
102 HttpSolrServer solrServer = null;
103 if (host == null || host.isEmpty()) {
107 solrServer =
new HttpSolrServer(
"http://" + host +
":" + Integer.toString(port) +
"/solr");
109 }
catch (SolrServerException ex) {
111 }
catch (IOException ex) {
112 String result = NbBundle.getMessage(
SolrSearchService.class,
"SolrConnectionCheck.HostnameOrPort");
113 String message = ex.getCause().getMessage().toLowerCase();
114 if (message.startsWith(SERVER_REFUSED_CONNECTION)) {
116 if (InetAddress.getByName(host).isReachable(IS_REACHABLE_TIMEOUT_MS)) {
118 result = Bundle.SolrConnectionCheck_Port();
120 result = NbBundle.getMessage(
SolrSearchService.class,
"SolrConnectionCheck.HostnameOrPort");
122 }
catch (IOException | MissingResourceException any) {
124 result = NbBundle.getMessage(
SolrSearchService.class,
"SolrConnectionCheck.HostnameOrPort");
126 }
else if (message.startsWith(BAD_IP_ADDRESS_FORMAT)) {
127 result = NbBundle.getMessage(
SolrSearchService.class,
"SolrConnectionCheck.Hostname");
130 }
catch (NumberFormatException ex) {
132 }
catch (IllegalArgumentException ex) {
135 if (null != solrServer) {
136 solrServer.shutdown();
141 @NbBundle.Messages({
"# {0} - case directory",
142 "SolrSearchService.exceptionMessage.noIndexMetadata=Unable to create IndexMetaData from caseDirectory: {0}",
143 "# {0} - case directory",
144 "SolrSearchService.exceptionMessage.noCurrentSolrCore=IndexMetadata did not contain a current Solr core so could not delete the case"
154 IndexMetadata indexMetadata;
156 indexMetadata =
new IndexMetadata(caseDirectory);
157 }
catch (IndexMetadata.TextIndexMetadataException ex) {
158 logger.log(Level.WARNING, NbBundle.getMessage(
SolrSearchService.class,
"SolrSearchService.exceptionMessage.noIndexMetadata", caseDirectory), ex);
162 String currentSchema = IndexFinder.getCurrentSchemaVersion();
163 String currentSolr = IndexFinder.getCurrentSolrVersion();
164 for (Index index : indexMetadata.getIndexes()) {
165 if (index.getSolrVersion().equals(currentSolr) && index.getSchemaVersion().equals(currentSchema)) {
171 logger.log(Level.WARNING, NbBundle.getMessage(
SolrSearchService.class,
"SolrSearchService.exceptionMessage.noCurrentSolrCore"));
176 public void close() throws IOException {
181 return NbBundle.getMessage(this.getClass(),
"SolrSearchService.ServiceName");
194 "SolrSearch.lookingForMetadata.msg=Looking for text index metadata file",
195 "SolrSearch.readingIndexes.msg=Reading text index metadata file",
196 "SolrSearch.findingIndexes.msg=Looking for existing text index directories",
197 "SolrSearch.creatingNewIndex.msg=Creating new text index",
198 "SolrSearch.checkingForLatestIndex.msg=Looking for text index with latest Solr and schema version",
199 "SolrSearch.indentifyingIndex.msg=Identifying text index to use",
200 "SolrSearch.openCore.msg=Opening text index",
201 "SolrSearch.complete.msg=Text index successfully opened"})
204 int totalNumProgressUnits = 7;
205 int progressUnitsCompleted = 0;
209 List<Index> indexes =
new ArrayList<>();
210 progress.
start(Bundle.SolrSearch_lookingForMetadata_msg(), totalNumProgressUnits);
211 if (IndexMetadata.isMetadataFilePresent(caseDirPath)) {
214 progressUnitsCompleted++;
215 progress.
progress(Bundle.SolrSearch_findingIndexes_msg(), progressUnitsCompleted);
216 IndexMetadata indexMetadata =
new IndexMetadata(caseDirPath);
217 indexes = indexMetadata.getIndexes();
218 }
catch (IndexMetadata.TextIndexMetadataException ex) {
219 logger.log(Level.SEVERE, String.format(
"Unable to read text index metadata file"), ex);
225 progressUnitsCompleted++;
226 progress.
progress(Bundle.SolrSearch_findingIndexes_msg(), progressUnitsCompleted);
227 Index oldIndex = IndexFinder.findOldIndexDir(theCase);
228 if (oldIndex != null) {
230 indexes.add(oldIndex);
239 Index currentVersionIndex = null;
240 if (indexes.isEmpty()) {
242 progressUnitsCompleted++;
243 progress.
progress(Bundle.SolrSearch_creatingNewIndex_msg(), progressUnitsCompleted);
244 currentVersionIndex = IndexFinder.createLatestVersionIndexDir(theCase);
246 indexes.add(currentVersionIndex);
249 progressUnitsCompleted++;
250 progress.
progress(Bundle.SolrSearch_checkingForLatestIndex_msg(), progressUnitsCompleted);
251 currentVersionIndex = IndexFinder.findLatestVersionIndexDir(indexes);
252 if (currentVersionIndex == null) {
254 progressUnitsCompleted++;
255 progress.
progress(Bundle.SolrSearch_indentifyingIndex_msg(), progressUnitsCompleted);
256 Index indexToUse = IndexFinder.identifyIndexToUse(indexes);
257 if (indexToUse == null) {
266 double currentSolrVersion = NumberUtils.toDouble(IndexFinder.getCurrentSolrVersion());
267 double indexSolrVersion = NumberUtils.toDouble(indexToUse.getSolrVersion());
268 if (indexSolrVersion == currentSolrVersion) {
272 JOptionPane optionPane =
new JOptionPane(
273 NbBundle.getMessage(
this.getClass(),
"SolrSearchService.IndexReadOnlyDialog.msg"),
274 JOptionPane.WARNING_MESSAGE,
275 JOptionPane.DEFAULT_OPTION);
277 SwingUtilities.invokeAndWait(() -> {
278 JDialog dialog = optionPane.createDialog(NbBundle.getMessage(
this.getClass(),
"SolrSearchService.IndexReadOnlyDialog.title"));
279 dialog.setVisible(
true);
281 }
catch (InterruptedException ex) {
284 }
catch (InvocationTargetException ex) {
289 currentVersionIndex = indexToUse;
299 if (!indexes.isEmpty()) {
300 IndexMetadata indexMetadata =
new IndexMetadata(caseDirPath, indexes);
302 }
catch (IndexMetadata.TextIndexMetadataException ex) {
308 progress.
progress(Bundle.SolrSearch_openCore_msg(), totalNumProgressUnits - 1);
314 progress.
progress(Bundle.SolrSearch_complete_msg(), totalNumProgressUnits);
332 KeywordSearchResultFactory.BlackboardResultWriter.stopAllWriters();
335 }
catch (InterruptedException ex) {
336 logger.log(Level.SEVERE,
"Unexpected interrupt while waiting for BlackboardResultWriters to terminate", ex);
volatile boolean cancelRequested
void indexArtifact(BlackboardArtifact artifact)
static boolean runningWithGUI
void progress(String message)
void openCaseResources(CaseContext context)
String getCaseDirectory()
static synchronized Server getServer()
void start(String message, int totalWorkUnits)
void closeCaseResources(CaseContext context)
void deleteTextIndex(CaseMetadata metadata)
ProgressIndicator getProgressIndicator()
synchronized static Logger getLogger(String name)
void tryConnect(String host, int port)