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;
 
   55 @ServiceProviders(value = {
 
   56     @ServiceProvider(service = KeywordSearchService.class),
 
   57     @ServiceProvider(service = AutopsyService.class)
 
   61     private static final String BAD_IP_ADDRESS_FORMAT = 
"ioexception occurred when talking to server"; 
 
   62     private static final String SERVER_REFUSED_CONNECTION = 
"server refused connection"; 
 
   63     private static final int IS_REACHABLE_TIMEOUT_MS = 1000;
 
   82     public void index(Content content) 
throws TskCoreException {
 
   96         if (content == null) {
 
   99         final Ingester ingester = Ingester.getDefault();
 
  100         if (content instanceof BlackboardArtifact) {
 
  101             BlackboardArtifact artifact = (BlackboardArtifact) content;
 
  102             if (artifact.getArtifactID() > 0) {
 
  112                 Reader blackboardExtractedTextReader = blackboardExtractor.
getReader();
 
  113                 String sourceName = artifact.getDisplayName() + 
"_" + artifact.getArtifactID();
 
  114                 ingester.indexMetaDataOnly(artifact, sourceName);
 
  115                 ingester.indexText(blackboardExtractedTextReader, artifact.getArtifactID(), sourceName, content, null);
 
  117                 throw new TskCoreException(
"Error indexing artifact", ex);
 
  122                 Reader contentExtractedTextReader = contentExtractor.
getReader();
 
  123                 ingester.indexText(contentExtractedTextReader, content.getId(), content.getName(), content, null);
 
  128                     Reader stringsExtractedTextReader = stringsExtractor.
getReader();
 
  129                     ingester.indexStrings(stringsExtractedTextReader, content.getId(), content.getName(), content, null);
 
  131                     throw new TskCoreException(
"Error indexing content", ex1);
 
  152         if (host == null || host.isEmpty()) {
 
  157         } 
catch (SolrServerException ex) {
 
  158             logger.log(Level.SEVERE, 
"Unable to connect to Solr server. Host: " + host + 
", port: " + port, ex);
 
  160         } 
catch (IOException ex) {
 
  161             logger.log(Level.SEVERE, 
"Unable to connect to Solr server. Host: " + host + 
", port: " + port, ex);
 
  162             String result = NbBundle.getMessage(
SolrSearchService.class, 
"SolrConnectionCheck.HostnameOrPort"); 
 
  163             String message = ex.getCause().getMessage().toLowerCase();
 
  164             if (message.startsWith(SERVER_REFUSED_CONNECTION)) {
 
  166                     if (InetAddress.getByName(host).isReachable(IS_REACHABLE_TIMEOUT_MS)) {
 
  168                         result = Bundle.SolrConnectionCheck_Port();
 
  170                         result = NbBundle.getMessage(
SolrSearchService.class, 
"SolrConnectionCheck.HostnameOrPort"); 
 
  172                 } 
catch (IOException | MissingResourceException any) {
 
  174                     result = NbBundle.getMessage(
SolrSearchService.class, 
"SolrConnectionCheck.HostnameOrPort"); 
 
  176             } 
else if (message.startsWith(BAD_IP_ADDRESS_FORMAT)) {
 
  177                 result = NbBundle.getMessage(
SolrSearchService.class, 
"SolrConnectionCheck.Hostname"); 
 
  180         } 
catch (NumberFormatException ex) {
 
  181             logger.log(Level.SEVERE, 
"Unable to connect to Solr server. Host: " + host + 
", port: " + port, ex);
 
  183         } 
catch (IllegalArgumentException ex) {
 
  184             logger.log(Level.SEVERE, 
"Unable to connect to Solr server. Host: " + host + 
", port: " + port, ex);
 
  202             ddsServer.deleteDataSource(dataSourceId);
 
  204             logger.log(Level.WARNING, NbBundle.getMessage(
SolrSearchService.class, 
"SolrSearchService.DeleteDataSource.msg", dataSourceId), ex);
 
  215         "# {0} - case directory", 
"SolrSearchService.exceptionMessage.noIndexMetadata=Unable to create IndexMetaData from case directory: {0}",
 
  216         "SolrSearchService.exceptionMessage.noCurrentSolrCore=IndexMetadata did not contain a current Solr core so could not delete the case",
 
  217         "# {0} - collection name", 
"SolrSearchService.exceptionMessage.unableToDeleteCollection=Unable to delete collection {0}",
 
  218         "# {0} - index folder path", 
"SolrSearchService.exceptionMessage.failedToDeleteIndexFiles=Failed to delete text index files at {0}" 
  223         IndexMetadata indexMetadata;
 
  225             indexMetadata = 
new IndexMetadata(caseDirectory);
 
  226         } 
catch (IndexMetadata.TextIndexMetadataException ex) {
 
  227             logger.log(Level.WARNING, NbBundle.getMessage(
SolrSearchService.class, 
"SolrSearchService.exceptionMessage.noIndexMetadata", caseDirectory), ex);
 
  231         if (indexMetadata.getIndexes().isEmpty()) {
 
  233                     "SolrSearchService.exceptionMessage.noCurrentSolrCore"));
 
  235                     "SolrSearchService.exceptionMessage.noCurrentSolrCore"));            
 
  239         for (Index index : indexMetadata.getIndexes()) {
 
  246             File indexDir = 
new File(index.getIndexPath()).getParentFile();
 
  247             if (indexDir.exists()) {
 
  257         return NbBundle.getMessage(this.getClass(), 
"SolrSearchService.ServiceName");
 
  270         "SolrSearch.lookingForMetadata.msg=Looking for text index metadata file",
 
  271         "SolrSearch.readingIndexes.msg=Reading text index metadata file",
 
  272         "SolrSearch.findingIndexes.msg=Looking for existing text index directories",
 
  273         "SolrSearch.creatingNewIndex.msg=Creating new text index",
 
  274         "SolrSearch.checkingForLatestIndex.msg=Looking for text index with latest Solr and schema version",
 
  275         "SolrSearch.indentifyingIndex.msg=Identifying text index to use",
 
  276         "SolrSearch.openCore.msg=Opening text index. For large cases this may take several minutes.",
 
  277         "# {0} - futureVersion", 
"# {1} - currentVersion",
 
  278         "SolrSearch.futureIndexVersion.msg=The text index for the case is for Solr {0}. This version of Autopsy is compatible with Solr {1}.",
 
  279         "SolrSearch.unableToFindIndex.msg=Unable to find index that can be used for this case",
 
  280         "SolrSearch.complete.msg=Text index successfully opened"})
 
  287         int totalNumProgressUnits = 7;
 
  288         int progressUnitsCompleted = 0;
 
  292         List<Index> indexes = 
new ArrayList<>();
 
  293         progress.
progress(Bundle.SolrSearch_lookingForMetadata_msg(), totalNumProgressUnits);
 
  294         if (IndexMetadata.isMetadataFilePresent(caseDirPath)) {
 
  297                 progressUnitsCompleted++;
 
  298                 progress.
progress(Bundle.SolrSearch_findingIndexes_msg(), progressUnitsCompleted);
 
  299                 IndexMetadata indexMetadata = 
new IndexMetadata(caseDirPath);
 
  300                 indexes = indexMetadata.getIndexes();
 
  301             } 
catch (IndexMetadata.TextIndexMetadataException ex) {
 
  302                 logger.log(Level.SEVERE, String.format(
"Unable to read text index metadata file"), ex);
 
  312         Index currentVersionIndex = null;
 
  313         if (indexes.isEmpty()) {
 
  315             progressUnitsCompleted++;
 
  316             progress.
progress(Bundle.SolrSearch_creatingNewIndex_msg(), progressUnitsCompleted);
 
  317             currentVersionIndex = IndexFinder.createLatestVersionIndex(theCase);
 
  319             indexes.add(currentVersionIndex);
 
  322             progressUnitsCompleted++;
 
  323             progress.
progress(Bundle.SolrSearch_checkingForLatestIndex_msg(), progressUnitsCompleted);
 
  324             currentVersionIndex = IndexFinder.findLatestVersionIndex(indexes);
 
  325             if (currentVersionIndex == null) {
 
  327                 progressUnitsCompleted++;
 
  328                 progress.
progress(Bundle.SolrSearch_indentifyingIndex_msg(), progressUnitsCompleted);
 
  329                 Index indexToUse = IndexFinder.identifyIndexToUse(indexes);
 
  330                 if (indexToUse == null) {
 
  333                     String futureIndexVersion = IndexFinder.isFutureIndexPresent(indexes);
 
  334                     if (!futureIndexVersion.isEmpty()) {
 
  335                         throw new AutopsyServiceException(Bundle.SolrSearch_futureIndexVersion_msg(futureIndexVersion, IndexFinder.getCurrentSolrVersion()));
 
  345                 if (!indexToUse.isCompatible(IndexFinder.getCurrentSchemaVersion())) {
 
  346                     String msg = 
"Text index schema version " + indexToUse.getSchemaVersion() + 
" is not compatible with current schema";
 
  347                     logger.log(Level.WARNING, msg);
 
  351                 currentVersionIndex = indexToUse;
 
  357             if (!indexes.isEmpty()) {
 
  358                 IndexMetadata indexMetadata = 
new IndexMetadata(caseDirPath, indexes);
 
  360         } 
catch (IndexMetadata.TextIndexMetadataException ex) {
 
  366             progress.
progress(Bundle.SolrSearch_openCore_msg(), totalNumProgressUnits - 1);
 
  377         progress.
progress(Bundle.SolrSearch_complete_msg(), totalNumProgressUnits);
 
  396         AdHocSearchChildFactory.BlackboardResultWriter.stopAllWriters();
 
  399         } 
catch (InterruptedException ex) {
 
  400             logger.log(Level.SEVERE, 
"Unexpected interrupt while waiting for BlackboardResultWriters to terminate", ex);
 
  419     @NbBundle.Messages(
"SolrSearchService.indexingError=Unable to index blackboard artifact.")
 
  421     void handleNewArtifacts(Blackboard.ArtifactsPostedEvent event) {
 
  422         for (BlackboardArtifact artifact : event.getArtifacts()) {
 
  423             if ((artifact.getArtifactTypeID() != BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) && 
 
  424                     (artifact.getArtifactTypeID() != BlackboardArtifact.ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT.getTypeID())){ 
 
  427                 } 
catch (TskCoreException ex) {
 
  429                     logger.log(Level.SEVERE, 
"Unable to index blackboard artifact " + artifact.getArtifactID(), ex); 
 
  430                     MessageNotifyUtil.Notify.error(Bundle.SolrSearchService_indexingError(), artifact.getDisplayName());
 
  447     public void indexArtifact(BlackboardArtifact artifact) 
throws TskCoreException {
 
  448         if (artifact == null) {
 
  454         if (artifact.getArtifactID() > 0) {
 
  457         final Ingester ingester = Ingester.getDefault();
 
  460             String sourceName = artifact.getDisplayName() + 
"_" + artifact.getArtifactID();
 
  462             Reader blackboardExtractedTextReader = blackboardExtractor.
getReader();
 
  463             ingester.indexMetaDataOnly(artifact, sourceName);
 
  464             ingester.indexText(blackboardExtractedTextReader, artifact.getId(), sourceName, artifact, null);
 
  466             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)