19 package org.sleuthkit.autopsy.keywordsearch;
22 import java.io.IOException;
23 import java.lang.reflect.InvocationTargetException;
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 javax.swing.JDialog;
30 import javax.swing.JOptionPane;
31 import javax.swing.SwingUtilities;
32 import org.apache.commons.lang.math.NumberUtils;
33 import org.apache.solr.client.solrj.SolrServerException;
34 import org.apache.solr.client.solrj.impl.HttpSolrServer;
35 import org.openide.util.NbBundle;
36 import org.openide.util.lookup.ServiceProvider;
37 import org.openide.util.lookup.ServiceProviders;
54 @ServiceProviders(value = {
55 @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;
75 public void indexArtifact(BlackboardArtifact artifact)
throws TskCoreException {
76 if (artifact == null) {
82 if (artifact.getArtifactID() > 0) {
85 final Ingester ingester = Ingester.getDefault();
88 ingester.indexMetaDataOnly(artifact);
89 ingester.indexText(
new ArtifactTextExtractor(), artifact, null);
90 }
catch (Ingester.IngesterException ex) {
91 throw new TskCoreException(ex.getCause().getMessage(), ex);
105 HttpSolrServer solrServer = null;
106 if (host == null || host.isEmpty()) {
110 solrServer =
new HttpSolrServer(
"http://" + host +
":" + Integer.toString(port) +
"/solr");
112 }
catch (SolrServerException ex) {
114 }
catch (IOException ex) {
115 String result = NbBundle.getMessage(
SolrSearchService.class,
"SolrConnectionCheck.HostnameOrPort");
116 String message = ex.getCause().getMessage().toLowerCase();
117 if (message.startsWith(SERVER_REFUSED_CONNECTION)) {
119 if (InetAddress.getByName(host).isReachable(IS_REACHABLE_TIMEOUT_MS)) {
121 result = Bundle.SolrConnectionCheck_Port();
123 result = NbBundle.getMessage(
SolrSearchService.class,
"SolrConnectionCheck.HostnameOrPort");
125 }
catch (IOException | MissingResourceException any) {
127 result = NbBundle.getMessage(
SolrSearchService.class,
"SolrConnectionCheck.HostnameOrPort");
129 }
else if (message.startsWith(BAD_IP_ADDRESS_FORMAT)) {
130 result = NbBundle.getMessage(
SolrSearchService.class,
"SolrConnectionCheck.Hostname");
133 }
catch (NumberFormatException ex) {
135 }
catch (IllegalArgumentException ex) {
138 if (null != solrServer) {
139 solrServer.shutdown();
150 "# {0} - case directory",
"SolrSearchService.exceptionMessage.noIndexMetadata=Unable to create IndexMetaData from case directory: {0}",
151 "SolrSearchService.exceptionMessage.noCurrentSolrCore=IndexMetadata did not contain a current Solr core so could not delete the case",
152 "# {0} - index folder path",
"SolrSearchService.exceptionMessage.failedToDeleteIndexFiles=Failed to delete text index files at {0}"
157 IndexMetadata indexMetadata;
159 indexMetadata =
new IndexMetadata(caseDirectory);
160 }
catch (IndexMetadata.TextIndexMetadataException ex) {
161 logger.log(Level.WARNING, NbBundle.getMessage(
SolrSearchService.class,
"SolrSearchService.exceptionMessage.noIndexMetadata", caseDirectory), ex);
165 String currentSchema = IndexFinder.getCurrentSchemaVersion();
166 String currentSolr = IndexFinder.getCurrentSolrVersion();
167 for (Index index : indexMetadata.getIndexes()) {
168 if (index.getSolrVersion().equals(currentSolr) && index.getSchemaVersion().equals(currentSchema)) {
183 "SolrSearchService.exceptionMessage.noCurrentSolrCore"));
185 "SolrSearchService.exceptionMessage.noCurrentSolrCore"));
189 public void close() throws IOException {
194 return NbBundle.getMessage(this.getClass(),
"SolrSearchService.ServiceName");
207 "SolrSearch.lookingForMetadata.msg=Looking for text index metadata file",
208 "SolrSearch.readingIndexes.msg=Reading text index metadata file",
209 "SolrSearch.findingIndexes.msg=Looking for existing text index directories",
210 "SolrSearch.creatingNewIndex.msg=Creating new text index",
211 "SolrSearch.checkingForLatestIndex.msg=Looking for text index with latest Solr and schema version",
212 "SolrSearch.indentifyingIndex.msg=Identifying text index to use",
213 "SolrSearch.openCore.msg=Opening text index",
214 "SolrSearch.complete.msg=Text index successfully opened"})
221 int totalNumProgressUnits = 7;
222 int progressUnitsCompleted = 0;
226 List<Index> indexes =
new ArrayList<>();
227 progress.
start(Bundle.SolrSearch_lookingForMetadata_msg(), totalNumProgressUnits);
228 if (IndexMetadata.isMetadataFilePresent(caseDirPath)) {
231 progressUnitsCompleted++;
232 progress.
progress(Bundle.SolrSearch_findingIndexes_msg(), progressUnitsCompleted);
233 IndexMetadata indexMetadata =
new IndexMetadata(caseDirPath);
234 indexes = indexMetadata.getIndexes();
235 }
catch (IndexMetadata.TextIndexMetadataException ex) {
236 logger.log(Level.SEVERE, String.format(
"Unable to read text index metadata file"), ex);
242 progressUnitsCompleted++;
243 progress.
progress(Bundle.SolrSearch_findingIndexes_msg(), progressUnitsCompleted);
244 Index oldIndex = IndexFinder.findOldIndexDir(theCase);
245 if (oldIndex != null) {
247 indexes.add(oldIndex);
256 Index currentVersionIndex = null;
257 if (indexes.isEmpty()) {
259 progressUnitsCompleted++;
260 progress.
progress(Bundle.SolrSearch_creatingNewIndex_msg(), progressUnitsCompleted);
261 currentVersionIndex = IndexFinder.createLatestVersionIndexDir(theCase);
263 indexes.add(currentVersionIndex);
266 progressUnitsCompleted++;
267 progress.
progress(Bundle.SolrSearch_checkingForLatestIndex_msg(), progressUnitsCompleted);
268 currentVersionIndex = IndexFinder.findLatestVersionIndexDir(indexes);
269 if (currentVersionIndex == null) {
271 progressUnitsCompleted++;
272 progress.
progress(Bundle.SolrSearch_indentifyingIndex_msg(), progressUnitsCompleted);
273 Index indexToUse = IndexFinder.identifyIndexToUse(indexes);
274 if (indexToUse == null) {
283 double currentSolrVersion = NumberUtils.toDouble(IndexFinder.getCurrentSolrVersion());
284 double indexSolrVersion = NumberUtils.toDouble(indexToUse.getSolrVersion());
285 if (indexSolrVersion == currentSolrVersion) {
289 JOptionPane optionPane =
new JOptionPane(
290 NbBundle.getMessage(
this.getClass(),
"SolrSearchService.IndexReadOnlyDialog.msg"),
291 JOptionPane.WARNING_MESSAGE,
292 JOptionPane.DEFAULT_OPTION);
294 SwingUtilities.invokeAndWait(() -> {
295 JDialog dialog = optionPane.createDialog(NbBundle.getMessage(
this.getClass(),
"SolrSearchService.IndexReadOnlyDialog.title"));
296 dialog.setVisible(
true);
298 }
catch (InterruptedException ex) {
301 }
catch (InvocationTargetException ex) {
306 currentVersionIndex = indexToUse;
316 if (!indexes.isEmpty()) {
317 IndexMetadata indexMetadata =
new IndexMetadata(caseDirPath, indexes);
319 }
catch (IndexMetadata.TextIndexMetadataException ex) {
325 progress.
progress(Bundle.SolrSearch_openCore_msg(), totalNumProgressUnits - 1);
331 progress.
progress(Bundle.SolrSearch_complete_msg(), totalNumProgressUnits);
349 KeywordSearchResultFactory.BlackboardResultWriter.stopAllWriters();
352 }
catch (InterruptedException ex) {
353 logger.log(Level.SEVERE,
"Unexpected interrupt while waiting for BlackboardResultWriters to terminate", ex);
void indexArtifact(BlackboardArtifact artifact)
static boolean runningWithGUI
void start(String message, int totalWorkUnits)
void openCaseResources(CaseContext context)
String getCaseDirectory()
static synchronized Server getServer()
ProgressIndicator getProgressIndicator()
volatile boolean cancelRequested
void closeCaseResources(CaseContext context)
void deleteTextIndex(CaseMetadata metadata)
synchronized static Logger getLogger(String name)
static boolean deleteDir(File dirPath)
void progress(String message)
void tryConnect(String host, int port)