19 package org.sleuthkit.autopsy.keywordsearch;
22 import java.io.IOException;
23 import java.io.Reader;
24 import java.net.InetAddress;
25 import java.util.ArrayList;
26 import java.util.List;
27 import java.util.MissingResourceException;
28 import java.util.logging.Level;
29 import org.apache.solr.client.solrj.SolrServerException;
30 import org.openide.util.NbBundle;
31 import org.openide.util.lookup.ServiceProvider;
32 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;
76 public void index(Content content)
throws TskCoreException {
77 if (content == null) {
80 final Ingester ingester = Ingester.getDefault();
81 if (content instanceof BlackboardArtifact) {
82 BlackboardArtifact artifact = (BlackboardArtifact) content;
83 if (artifact.getArtifactID() > 0) {
93 Reader blackboardExtractedTextReader = blackboardExtractor.
getReader();
94 String sourceName = artifact.getDisplayName() +
"_" + artifact.getArtifactID();
95 ingester.indexMetaDataOnly(artifact, sourceName);
96 ingester.indexText(blackboardExtractedTextReader, artifact.getArtifactID(), sourceName, content, null);
98 throw new TskCoreException(
"Error indexing artifact", ex);
103 Reader contentExtractedTextReader = contentExtractor.
getReader();
104 ingester.indexText(contentExtractedTextReader, content.getId(), content.getName(), content, null);
109 Reader stringsExtractedTextReader = stringsExtractor.
getReader();
110 ingester.indexStrings(stringsExtractedTextReader, content.getId(), content.getName(), content, null);
112 throw new TskCoreException(
"Error indexing content", ex1);
133 if (host == null || host.isEmpty()) {
138 }
catch (SolrServerException ex) {
139 logger.log(Level.SEVERE,
"Unable to connect to Solr server. Host: " + host +
", port: " + port, ex);
141 }
catch (IOException ex) {
142 logger.log(Level.SEVERE,
"Unable to connect to Solr server. Host: " + host +
", port: " + port, ex);
143 String result = NbBundle.getMessage(
SolrSearchService.class,
"SolrConnectionCheck.HostnameOrPort");
144 String message = ex.getCause().getMessage().toLowerCase();
145 if (message.startsWith(SERVER_REFUSED_CONNECTION)) {
147 if (InetAddress.getByName(host).isReachable(IS_REACHABLE_TIMEOUT_MS)) {
149 result = Bundle.SolrConnectionCheck_Port();
151 result = NbBundle.getMessage(
SolrSearchService.class,
"SolrConnectionCheck.HostnameOrPort");
153 }
catch (IOException | MissingResourceException any) {
155 result = NbBundle.getMessage(
SolrSearchService.class,
"SolrConnectionCheck.HostnameOrPort");
157 }
else if (message.startsWith(BAD_IP_ADDRESS_FORMAT)) {
158 result = NbBundle.getMessage(
SolrSearchService.class,
"SolrConnectionCheck.Hostname");
161 }
catch (NumberFormatException ex) {
162 logger.log(Level.SEVERE,
"Unable to connect to Solr server. Host: " + host +
", port: " + port, ex);
164 }
catch (IllegalArgumentException ex) {
165 logger.log(Level.SEVERE,
"Unable to connect to Solr server. Host: " + host +
", port: " + port, ex);
183 ddsServer.deleteDataSource(dataSourceId);
185 logger.log(Level.WARNING, NbBundle.getMessage(
SolrSearchService.class,
"SolrSearchService.DeleteDataSource.msg", dataSourceId), ex);
196 "# {0} - case directory",
"SolrSearchService.exceptionMessage.noIndexMetadata=Unable to create IndexMetaData from case directory: {0}",
197 "SolrSearchService.exceptionMessage.noCurrentSolrCore=IndexMetadata did not contain a current Solr core so could not delete the case",
198 "# {0} - collection name",
"SolrSearchService.exceptionMessage.unableToDeleteCollection=Unable to delete collection {0}",
199 "# {0} - index folder path",
"SolrSearchService.exceptionMessage.failedToDeleteIndexFiles=Failed to delete text index files at {0}"
204 IndexMetadata indexMetadata;
206 indexMetadata =
new IndexMetadata(caseDirectory);
207 }
catch (IndexMetadata.TextIndexMetadataException ex) {
208 logger.log(Level.WARNING, NbBundle.getMessage(
SolrSearchService.class,
"SolrSearchService.exceptionMessage.noIndexMetadata", caseDirectory), ex);
212 if (indexMetadata.getIndexes().isEmpty()) {
214 "SolrSearchService.exceptionMessage.noCurrentSolrCore"));
216 "SolrSearchService.exceptionMessage.noCurrentSolrCore"));
220 for (Index index : indexMetadata.getIndexes()) {
227 File indexDir =
new File(index.getIndexPath()).getParentFile();
228 if (indexDir.exists()) {
238 return NbBundle.getMessage(this.getClass(),
"SolrSearchService.ServiceName");
251 "SolrSearch.lookingForMetadata.msg=Looking for text index metadata file",
252 "SolrSearch.readingIndexes.msg=Reading text index metadata file",
253 "SolrSearch.findingIndexes.msg=Looking for existing text index directories",
254 "SolrSearch.creatingNewIndex.msg=Creating new text index",
255 "SolrSearch.checkingForLatestIndex.msg=Looking for text index with latest Solr and schema version",
256 "SolrSearch.indentifyingIndex.msg=Identifying text index to use",
257 "SolrSearch.openCore.msg=Opening text index. For large cases this may take several minutes.",
258 "# {0} - futureVersion",
"# {1} - currentVersion",
259 "SolrSearch.futureIndexVersion.msg=The text index for the case is for Solr {0}. This version of Autopsy is compatible with Solr {1}.",
260 "SolrSearch.unableToFindIndex.msg=Unable to find index that can be used for this case",
261 "SolrSearch.complete.msg=Text index successfully opened"})
268 int totalNumProgressUnits = 7;
269 int progressUnitsCompleted = 0;
273 List<Index> indexes =
new ArrayList<>();
274 progress.
progress(Bundle.SolrSearch_lookingForMetadata_msg(), totalNumProgressUnits);
275 if (IndexMetadata.isMetadataFilePresent(caseDirPath)) {
278 progressUnitsCompleted++;
279 progress.
progress(Bundle.SolrSearch_findingIndexes_msg(), progressUnitsCompleted);
280 IndexMetadata indexMetadata =
new IndexMetadata(caseDirPath);
281 indexes = indexMetadata.getIndexes();
282 }
catch (IndexMetadata.TextIndexMetadataException ex) {
283 logger.log(Level.SEVERE, String.format(
"Unable to read text index metadata file"), ex);
293 Index currentVersionIndex = null;
294 if (indexes.isEmpty()) {
296 progressUnitsCompleted++;
297 progress.
progress(Bundle.SolrSearch_creatingNewIndex_msg(), progressUnitsCompleted);
298 currentVersionIndex = IndexFinder.createLatestVersionIndex(theCase);
300 indexes.add(currentVersionIndex);
303 progressUnitsCompleted++;
304 progress.
progress(Bundle.SolrSearch_checkingForLatestIndex_msg(), progressUnitsCompleted);
305 currentVersionIndex = IndexFinder.findLatestVersionIndex(indexes);
306 if (currentVersionIndex == null) {
308 progressUnitsCompleted++;
309 progress.
progress(Bundle.SolrSearch_indentifyingIndex_msg(), progressUnitsCompleted);
310 Index indexToUse = IndexFinder.identifyIndexToUse(indexes);
311 if (indexToUse == null) {
314 String futureIndexVersion = IndexFinder.isFutureIndexPresent(indexes);
315 if (!futureIndexVersion.isEmpty()) {
316 throw new AutopsyServiceException(Bundle.SolrSearch_futureIndexVersion_msg(futureIndexVersion, IndexFinder.getCurrentSolrVersion()));
326 if (!indexToUse.isCompatible(IndexFinder.getCurrentSchemaVersion())) {
327 String msg =
"Text index schema version " + indexToUse.getSchemaVersion() +
" is not compatible with current schema";
328 logger.log(Level.WARNING, msg);
332 currentVersionIndex = indexToUse;
338 if (!indexes.isEmpty()) {
339 IndexMetadata indexMetadata =
new IndexMetadata(caseDirPath, indexes);
341 }
catch (IndexMetadata.TextIndexMetadataException ex) {
347 progress.
progress(Bundle.SolrSearch_openCore_msg(), totalNumProgressUnits - 1);
358 progress.
progress(Bundle.SolrSearch_complete_msg(), totalNumProgressUnits);
377 AdHocSearchChildFactory.BlackboardResultWriter.stopAllWriters();
380 }
catch (InterruptedException ex) {
381 logger.log(Level.SEVERE,
"Unexpected interrupt while waiting for BlackboardResultWriters to terminate", ex);
406 public void indexArtifact(BlackboardArtifact artifact)
throws TskCoreException {
407 if (artifact == null) {
413 if (artifact.getArtifactID() > 0) {
416 final Ingester ingester = Ingester.getDefault();
419 String sourceName = artifact.getDisplayName() +
"_" + artifact.getArtifactID();
421 Reader blackboardExtractedTextReader = blackboardExtractor.
getReader();
422 ingester.indexMetaDataOnly(artifact, sourceName);
423 ingester.indexText(blackboardExtractedTextReader, artifact.getId(), sourceName, artifact, null);
425 throw new TskCoreException(ex.getCause().getMessage(), ex);
static synchronized IngestManager getInstance()
void index(Content content)
void indexArtifact(BlackboardArtifact artifact)
void openCaseResources(CaseContext context)
String getCaseDirectory()
static synchronized Server getServer()
boolean isIngestRunning()
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)