19 package org.sleuthkit.autopsy.keywordsearch;
21 import com.google.common.eventbus.Subscribe;
23 import java.io.IOException;
24 import java.io.Reader;
25 import java.net.InetAddress;
26 import java.util.ArrayList;
27 import java.util.List;
28 import java.util.MissingResourceException;
29 import java.util.logging.Level;
30 import org.apache.solr.client.solrj.SolrServerException;
31 import org.openide.util.NbBundle;
32 import org.openide.util.lookup.ServiceProvider;
33 import org.openide.util.lookup.ServiceProviders;
54 @ServiceProviders(value = {
55 @ServiceProvider(service = KeywordSearchService.class),
56 @ServiceProvider(service = AutopsyService.class)
60 private static final String BAD_IP_ADDRESS_FORMAT =
"ioexception occurred when talking to server";
61 private static final String SERVER_REFUSED_CONNECTION =
"server refused connection";
62 private static final int IS_REACHABLE_TIMEOUT_MS = 1000;
81 public void index(Content content)
throws TskCoreException {
95 if (content == null) {
98 final Ingester ingester = Ingester.getDefault();
99 if (content instanceof BlackboardArtifact) {
100 BlackboardArtifact artifact = (BlackboardArtifact) content;
101 if (artifact.getArtifactID() > 0) {
111 Reader blackboardExtractedTextReader = blackboardExtractor.
getReader();
112 String sourceName = artifact.getDisplayName() +
"_" + artifact.getArtifactID();
113 ingester.indexMetaDataOnly(artifact, sourceName);
114 ingester.indexText(blackboardExtractedTextReader, artifact.getArtifactID(), sourceName, content, null);
116 throw new TskCoreException(
"Error indexing artifact", ex);
121 Reader contentExtractedTextReader = contentExtractor.
getReader();
122 ingester.indexText(contentExtractedTextReader, content.getId(), content.getName(), content, null);
127 Reader stringsExtractedTextReader = stringsExtractor.
getReader();
128 ingester.indexStrings(stringsExtractedTextReader, content.getId(), content.getName(), content, null);
130 throw new TskCoreException(
"Error indexing content", ex1);
147 if (host == null || host.isEmpty()) {
152 }
catch (SolrServerException ex) {
153 logger.log(Level.SEVERE,
"Unable to connect to Solr server. Host: " + host +
", port: " + port, ex);
155 }
catch (IOException ex) {
156 logger.log(Level.SEVERE,
"Unable to connect to Solr server. Host: " + host +
", port: " + port, ex);
157 String result = NbBundle.getMessage(
SolrSearchService.class,
"SolrConnectionCheck.HostnameOrPort");
158 String message = ex.getCause().getMessage().toLowerCase();
159 if (message.startsWith(SERVER_REFUSED_CONNECTION)) {
161 if (InetAddress.getByName(host).isReachable(IS_REACHABLE_TIMEOUT_MS)) {
163 result = Bundle.SolrConnectionCheck_Port();
165 result = NbBundle.getMessage(
SolrSearchService.class,
"SolrConnectionCheck.HostnameOrPort");
167 }
catch (IOException | MissingResourceException any) {
169 result = NbBundle.getMessage(
SolrSearchService.class,
"SolrConnectionCheck.HostnameOrPort");
171 }
else if (message.startsWith(BAD_IP_ADDRESS_FORMAT)) {
172 result = NbBundle.getMessage(
SolrSearchService.class,
"SolrConnectionCheck.Hostname");
175 }
catch (NumberFormatException ex) {
176 logger.log(Level.SEVERE,
"Unable to connect to Solr server. Host: " + host +
", port: " + port, ex);
178 }
catch (IllegalArgumentException ex) {
179 logger.log(Level.SEVERE,
"Unable to connect to Solr server. Host: " + host +
", port: " + port, ex);
197 ddsServer.deleteDataSource(dataSourceId);
199 logger.log(Level.WARNING, NbBundle.getMessage(
SolrSearchService.class,
"SolrSearchService.DeleteDataSource.msg", dataSourceId), ex);
210 "# {0} - case directory",
"SolrSearchService.exceptionMessage.noIndexMetadata=Unable to create IndexMetaData from case directory: {0}",
211 "SolrSearchService.exceptionMessage.noCurrentSolrCore=IndexMetadata did not contain a current Solr core so could not delete the case",
212 "# {0} - collection name",
"SolrSearchService.exceptionMessage.unableToDeleteCollection=Unable to delete collection {0}",
213 "# {0} - index folder path",
"SolrSearchService.exceptionMessage.failedToDeleteIndexFiles=Failed to delete text index files at {0}"
218 IndexMetadata indexMetadata;
220 indexMetadata =
new IndexMetadata(caseDirectory);
221 }
catch (IndexMetadata.TextIndexMetadataException ex) {
222 logger.log(Level.WARNING, NbBundle.getMessage(
SolrSearchService.class,
"SolrSearchService.exceptionMessage.noIndexMetadata", caseDirectory), ex);
226 if (indexMetadata.getIndexes().isEmpty()) {
228 "SolrSearchService.exceptionMessage.noCurrentSolrCore"));
230 "SolrSearchService.exceptionMessage.noCurrentSolrCore"));
234 for (Index index : indexMetadata.getIndexes()) {
241 File indexDir =
new File(index.getIndexPath()).getParentFile();
242 if (indexDir.exists()) {
252 return NbBundle.getMessage(this.getClass(),
"SolrSearchService.ServiceName");
265 "SolrSearch.lookingForMetadata.msg=Looking for text index metadata file",
266 "SolrSearch.readingIndexes.msg=Reading text index metadata file",
267 "SolrSearch.findingIndexes.msg=Looking for existing text index directories",
268 "SolrSearch.creatingNewIndex.msg=Creating new text index",
269 "SolrSearch.checkingForLatestIndex.msg=Looking for text index with latest Solr and schema version",
270 "SolrSearch.indentifyingIndex.msg=Identifying text index to use",
271 "SolrSearch.openCore.msg=Opening text index. For large cases this may take several minutes.",
272 "SolrSearch.complete.msg=Text index successfully opened"})
279 int totalNumProgressUnits = 7;
280 int progressUnitsCompleted = 0;
284 List<Index> indexes =
new ArrayList<>();
285 progress.
progress(Bundle.SolrSearch_lookingForMetadata_msg(), totalNumProgressUnits);
286 if (IndexMetadata.isMetadataFilePresent(caseDirPath)) {
289 progressUnitsCompleted++;
290 progress.
progress(Bundle.SolrSearch_findingIndexes_msg(), progressUnitsCompleted);
291 IndexMetadata indexMetadata =
new IndexMetadata(caseDirPath);
292 indexes = indexMetadata.getIndexes();
293 }
catch (IndexMetadata.TextIndexMetadataException ex) {
294 logger.log(Level.SEVERE, String.format(
"Unable to read text index metadata file"), ex);
304 Index currentVersionIndex = null;
305 if (indexes.isEmpty()) {
307 progressUnitsCompleted++;
308 progress.
progress(Bundle.SolrSearch_creatingNewIndex_msg(), progressUnitsCompleted);
309 currentVersionIndex = IndexFinder.createLatestVersionIndexDir(theCase);
311 indexes.add(currentVersionIndex);
314 progressUnitsCompleted++;
315 progress.
progress(Bundle.SolrSearch_checkingForLatestIndex_msg(), progressUnitsCompleted);
316 currentVersionIndex = IndexFinder.findLatestVersionIndexDir(indexes);
317 if (currentVersionIndex == null) {
319 progressUnitsCompleted++;
320 progress.
progress(Bundle.SolrSearch_indentifyingIndex_msg(), progressUnitsCompleted);
321 Index indexToUse = IndexFinder.identifyIndexToUse(indexes);
322 if (indexToUse == null) {
332 if (!indexToUse.isCompatible(IndexFinder.getCurrentSchemaVersion())) {
333 String msg =
"Text index schema version " + indexToUse.getSchemaVersion() +
" is not compatible with current schema";
334 logger.log(Level.WARNING, msg);
338 currentVersionIndex = indexToUse;
344 if (!indexes.isEmpty()) {
345 IndexMetadata indexMetadata =
new IndexMetadata(caseDirPath, indexes);
347 }
catch (IndexMetadata.TextIndexMetadataException ex) {
353 progress.
progress(Bundle.SolrSearch_openCore_msg(), totalNumProgressUnits - 1);
364 progress.
progress(Bundle.SolrSearch_complete_msg(), totalNumProgressUnits);
383 AdHocSearchChildFactory.BlackboardResultWriter.stopAllWriters();
386 }
catch (InterruptedException ex) {
387 logger.log(Level.SEVERE,
"Unexpected interrupt while waiting for BlackboardResultWriters to terminate", ex);
404 @NbBundle.Messages(
"SolrSearchService.indexingError=Unable to index blackboard artifact.")
406 void handleNewArtifacts(Blackboard.ArtifactsPostedEvent event) {
407 for (BlackboardArtifact artifact : event.getArtifacts()) {
408 if ((artifact.getArtifactTypeID() != BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) &&
409 (artifact.getArtifactTypeID() != BlackboardArtifact.ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT.getTypeID())){
412 }
catch (TskCoreException ex) {
414 logger.log(Level.SEVERE,
"Unable to index blackboard artifact " + artifact.getArtifactID(), ex);
415 MessageNotifyUtil.Notify.error(Bundle.SolrSearchService_indexingError(), artifact.getDisplayName());
432 public void indexArtifact(BlackboardArtifact artifact)
throws TskCoreException {
433 if (artifact == null) {
439 if (artifact.getArtifactID() > 0) {
442 final Ingester ingester = Ingester.getDefault();
445 String sourceName = artifact.getDisplayName() +
"_" + artifact.getArtifactID();
447 Reader blackboardExtractedTextReader = blackboardExtractor.
getReader();
448 ingester.indexMetaDataOnly(artifact, sourceName);
449 ingester.indexText(blackboardExtractedTextReader, artifact.getId(), sourceName, artifact, null);
451 throw new TskCoreException(ex.getCause().getMessage(), ex);
void index(Content content)
void indexArtifact(BlackboardArtifact artifact)
void openCaseResources(CaseContext context)
String getCaseDirectory()
static synchronized Server getServer()
ProgressIndicator getProgressIndicator()
volatile boolean cancelRequested
void closeCaseResources(CaseContext context)
void deleteTextIndex(CaseMetadata metadata)
SleuthkitCase getSleuthkitCase()
void deleteDataSource(Long dataSourceId)
synchronized static Logger getLogger(String name)
static boolean deleteDir(File dirPath)
void progress(String message)
void tryConnect(String host, int port)