19 package org.sleuthkit.autopsy.keywordsearch;
21 import java.awt.event.ActionEvent;
22 import java.beans.PropertyChangeListener;
23 import java.io.BufferedReader;
24 import java.io.BufferedWriter;
26 import java.io.FileOutputStream;
27 import java.io.IOException;
28 import java.io.InputStream;
29 import java.io.InputStreamReader;
30 import java.io.OutputStream;
31 import java.io.OutputStreamWriter;
32 import java.net.ConnectException;
33 import java.net.ServerSocket;
34 import java.net.SocketException;
35 import java.nio.charset.Charset;
36 import java.nio.file.Files;
37 import java.nio.file.Path;
38 import java.nio.file.Paths;
39 import java.util.ArrayList;
40 import java.util.Arrays;
41 import java.util.Collection;
42 import java.util.Iterator;
43 import java.util.List;
44 import java.util.Random;
45 import java.util.concurrent.TimeUnit;
46 import java.util.concurrent.locks.ReentrantReadWriteLock;
47 import java.util.logging.Level;
48 import javax.swing.AbstractAction;
49 import org.apache.solr.client.solrj.SolrQuery;
50 import org.apache.solr.client.solrj.SolrRequest;
51 import org.apache.solr.client.solrj.SolrServerException;
52 import org.apache.solr.client.solrj.impl.HttpSolrServer;
53 import org.apache.solr.client.solrj.impl.XMLResponseParser;
54 import org.apache.solr.client.solrj.request.CoreAdminRequest;
55 import org.apache.solr.client.solrj.response.CoreAdminResponse;
56 import org.apache.solr.client.solrj.response.QueryResponse;
57 import org.apache.solr.client.solrj.response.TermsResponse;
58 import org.apache.solr.common.SolrDocument;
59 import org.apache.solr.common.SolrDocumentList;
60 import org.apache.solr.common.SolrException;
61 import org.apache.solr.common.SolrInputDocument;
62 import org.apache.solr.common.params.CoreAdminParams;
63 import org.apache.solr.common.util.NamedList;
64 import org.openide.modules.InstalledFileLocator;
65 import org.openide.modules.Places;
66 import org.openide.util.NbBundle;
67 import org.openide.windows.WindowManager;
94 public String toString() {
100 public String toString() {
107 public String toString() {
114 public String toString() {
115 return "content_str";
121 public String toString() {
129 public String toString() {
135 public String toString() {
141 public String toString() {
147 public String toString() {
154 public String toString() {
161 public String toString() {
168 public String toString() {
175 public String toString() {
181 public String toString() {
187 public String toString() {
198 public String toString() {
215 static final String PROPERTIES_FILE = KeywordSearchSettings.MODULE_NAME;
216 static final String PROPERTIES_CURRENT_SERVER_PORT =
"IndexingServerPort";
217 static final String PROPERTIES_CURRENT_STOP_PORT =
"IndexingServerStopPort";
218 private static final String
KEY =
"jjk#09s";
219 static final String DEFAULT_SOLR_SERVER_HOST =
"localhost";
220 static final int DEFAULT_SOLR_SERVER_PORT = 23232;
221 static final int DEFAULT_SOLR_STOP_PORT = 34343;
224 private static final boolean DEBUG =
false;
225 private static final String
SOLR =
"solr";
255 this.localSolrServer =
new HttpSolrServer(
"http://localhost:" + currentSolrServerPort +
"/solr");
256 serverAction =
new ServerAction();
257 solrFolder = InstalledFileLocator.getDefault().locate(
"solr",
Server.class.getPackage().getName(),
false);
261 if (!solrHome.toFile().exists()) {
263 Files.createDirectory(solrHome);
264 Files.copy(Paths.get(solrFolder.getAbsolutePath(),
"solr",
"solr.xml"), solrHome.resolve(
"solr.xml"));
265 Files.copy(Paths.get(solrFolder.getAbsolutePath(),
"solr",
"zoo.cfg"), solrHome.resolve(
"zoo.cfg"));
266 }
catch (IOException ex) {
267 logger.log(Level.SEVERE,
"Failed to create Solr home folder:", ex);
270 currentCoreLock =
new ReentrantReadWriteLock(
true);
272 logger.log(Level.INFO,
"Created Server instance using Java at {0}", javaPath);
280 }
catch (NumberFormatException nfe) {
281 logger.log(Level.WARNING,
"Could not decode indexing server port, value was not a valid port number, using the default. ", nfe);
282 currentSolrServerPort = DEFAULT_SOLR_SERVER_PORT;
285 currentSolrServerPort = DEFAULT_SOLR_SERVER_PORT;
292 }
catch (NumberFormatException nfe) {
293 logger.log(Level.WARNING,
"Could not decode indexing server stop port, value was not a valid port number, using default", nfe);
294 currentSolrStopPort = DEFAULT_SOLR_STOP_PORT;
297 currentSolrStopPort = DEFAULT_SOLR_STOP_PORT;
303 public void finalize() throws java.lang.Throwable {
309 serverAction.addPropertyChangeListener(l);
312 int getCurrentSolrServerPort() {
316 int getCurrentSolrStopPort() {
327 volatile boolean doRun =
true;
330 this.stream = stream;
332 final String log = Places.getUserDirectory().getAbsolutePath()
333 + File.separator +
"var" + File.separator +
"log"
334 + File.separator +
"solr.log." + type;
335 File outputFile =
new File(log.concat(
".0"));
336 File first =
new File(log.concat(
".1"));
337 File second =
new File(log.concat(
".2"));
338 if (second.exists()) {
341 if (first.exists()) {
342 first.renameTo(second);
344 if (outputFile.exists()) {
345 outputFile.renameTo(first);
347 outputFile.createNewFile();
349 out =
new FileOutputStream(outputFile);
351 }
catch (Exception ex) {
352 logger.log(Level.WARNING,
"Failed to create solr log file", ex);
363 try (InputStreamReader isr =
new InputStreamReader(stream);
364 BufferedReader br =
new BufferedReader(isr);
366 BufferedWriter bw =
new BufferedWriter(osw);) {
369 while (doRun && (line = br.readLine()) != null) {
378 }
catch (IOException ex) {
379 logger.log(Level.SEVERE,
"Error redirecting Solr output stream", ex);
396 List<String> commandLine =
new ArrayList<>();
397 commandLine.add(javaPath);
398 commandLine.add(MAX_SOLR_MEM_MB_PAR);
399 commandLine.add(
"-DSTOP.PORT=" + currentSolrStopPort);
400 commandLine.add(
"-Djetty.port=" + currentSolrServerPort);
401 commandLine.add(
"-DSTOP.KEY=" + KEY);
402 commandLine.add(
"-jar");
403 commandLine.add(
"start.jar");
405 commandLine.addAll(solrArguments);
407 ProcessBuilder solrProcessBuilder =
new ProcessBuilder(commandLine);
408 solrProcessBuilder.directory(solrFolder);
411 Path solrStdoutPath = Paths.get(Places.getUserDirectory().getAbsolutePath(),
"var",
"log",
"solr.log.stdout");
412 solrProcessBuilder.redirectOutput(solrStdoutPath.toFile());
414 Path solrStderrPath = Paths.get(Places.getUserDirectory().getAbsolutePath(),
"var",
"log",
"solr.log.stderr");
415 solrProcessBuilder.redirectError(solrStderrPath.toFile());
417 logger.log(Level.INFO,
"Running Solr command: {0}", solrProcessBuilder.command());
418 Process process = solrProcessBuilder.start();
419 logger.log(Level.INFO,
"Finished running Solr command");
428 List<Long> getSolrPIDs() {
429 List<Long> pids =
new ArrayList<>();
432 final String pidsQuery =
"Args.*.eq=-DSTOP.KEY=" + KEY +
",Args.*.eq=start.jar";
435 if (pidsArr != null) {
436 for (
int i = 0; i < pidsArr.length; ++i) {
437 pids.add(pidsArr[i]);
449 List<Long> solrPids = getSolrPIDs();
450 for (
long pid : solrPids) {
451 logger.log(Level.INFO,
"Trying to kill old Solr process, PID: {0}", pid);
452 PlatformUtil.killProcess(pid);
462 "Server.status.failed.msg=Local Solr server did not respond to status request. This may be because the server failed to start or is taking too long to initialize.",})
463 void start()
throws KeywordSearchModuleException, SolrServerNoPortException {
469 if (!isPortAvailable(currentSolrServerPort)) {
473 final List<Long> pids = this.getSolrPIDs();
477 if (pids.isEmpty()) {
478 throw new SolrServerNoPortException(currentSolrServerPort);
487 if (!isPortAvailable(currentSolrServerPort)) {
488 throw new SolrServerNoPortException(currentSolrServerPort);
490 if (!isPortAvailable(currentSolrStopPort)) {
491 throw new SolrServerNoPortException(currentSolrStopPort);
495 logger.log(Level.INFO,
"Starting Solr server from: {0}", solrFolder.getAbsolutePath());
497 if (isPortAvailable(currentSolrServerPort)) {
498 logger.log(Level.INFO,
"Port [{0}] available, starting Solr", currentSolrServerPort);
501 Arrays.asList(
"-Dbootstrap_confdir=../solr/configsets/AutopsyConfig/conf",
502 "-Dcollection.configName=AutopsyConfig")));
505 for (
int numRetries = 0; numRetries < 6; numRetries++) {
507 final List<Long> pids = this.getSolrPIDs();
508 logger.log(Level.INFO,
"New Solr process PID: {0}", pids);
515 TimeUnit.SECONDS.sleep(5);
516 }
catch (InterruptedException ex) {
517 logger.log(Level.WARNING,
"Timer interrupted");
523 logger.log(Level.WARNING,
"Local Solr server failed to respond to status requests.");
524 WindowManager.getDefault().invokeWhenUIReady(
new Runnable() {
527 MessageNotifyUtil.Notify.error(
528 NbBundle.getMessage(
this.getClass(),
"Installer.errorInitKsmMsg"),
529 Bundle.Server_status_failed_msg());
532 }
catch (SecurityException ex) {
533 logger.log(Level.SEVERE,
"Could not start Solr process!", ex);
534 throw new KeywordSearchModuleException(
535 NbBundle.getMessage(
this.getClass(),
"Server.start.exception.cantStartSolr.msg"), ex);
536 }
catch (IOException ex) {
537 logger.log(Level.SEVERE,
"Could not start Solr server process!", ex);
538 throw new KeywordSearchModuleException(
539 NbBundle.getMessage(
this.getClass(),
"Server.start.exception.cantStartSolr.msg2"), ex);
549 static boolean isPortAvailable(
int port) {
550 ServerSocket ss = null;
553 ss =
new ServerSocket(port, 0, java.net.Inet4Address.getByName(
"localhost"));
555 ss.setReuseAddress(
true);
560 }
catch (IOException e) {
565 }
catch (IOException e) {
580 void changeSolrServerPort(
int port) {
581 currentSolrServerPort = port;
582 ModuleSettings.setConfigSetting(PROPERTIES_FILE, PROPERTIES_CURRENT_SERVER_PORT, String.valueOf(port));
590 void changeSolrStopPort(
int port) {
591 currentSolrStopPort = port;
592 ModuleSettings.setConfigSetting(PROPERTIES_FILE, PROPERTIES_CURRENT_STOP_PORT, String.valueOf(port));
600 synchronized void stop() {
605 }
catch (KeywordSearchModuleException e) {
606 logger.log(Level.WARNING,
"Failed to close core: ", e);
610 logger.log(Level.INFO,
"Stopping Solr server from: {0}", solrFolder.getAbsolutePath());
613 Process process =
runSolrCommand(
new ArrayList<>(Arrays.asList(
"--stop")));
615 logger.log(Level.INFO,
"Waiting for Solr server to stop");
619 if (curSolrProcess != null) {
620 curSolrProcess.destroy();
621 curSolrProcess = null;
624 }
catch (IOException | InterruptedException ex) {
625 logger.log(Level.WARNING,
"Error while attempting to stop Solr server", ex);
629 if (errorRedirectThread != null) {
630 errorRedirectThread.stopRun();
631 errorRedirectThread = null;
638 logger.log(Level.INFO,
"Finished stopping Solr server");
649 synchronized boolean isRunning() throws KeywordSearchModuleException {
652 if (isPortAvailable(currentSolrServerPort)) {
659 connectToSolrServer(localSolrServer);
661 logger.log(Level.INFO,
"Solr server is running");
662 }
catch (SolrServerException ex) {
664 Throwable cause = ex.getRootCause();
669 if (cause instanceof ConnectException || cause instanceof SocketException) {
670 logger.log(Level.INFO,
"Solr server is not running, cause: {0}", cause.getMessage());
673 throw new KeywordSearchModuleException(
674 NbBundle.getMessage(
this.getClass(),
"Server.isRunning.exception.errCheckSolrRunning.msg"), ex);
676 }
catch (SolrException ex) {
678 logger.log(Level.INFO,
"Solr server is not running", ex);
680 }
catch (IOException ex) {
681 throw new KeywordSearchModuleException(
682 NbBundle.getMessage(
this.getClass(),
"Server.isRunning.exception.errCheckSolrRunning.msg2"), ex);
700 void openCoreForCase(Case theCase, Index index)
throws KeywordSearchModuleException {
701 currentCoreLock.writeLock().lock();
703 currentCore =
openCore(theCase, index);
708 }
catch (NoOpenCoreException ex) {
709 throw new KeywordSearchModuleException(NbBundle.getMessage(
this.getClass(),
"Server.openCore.exception.cantOpen.msg"), ex);
712 serverAction.putValue(CORE_EVT, CORE_EVT_STATES.STARTED);
714 currentCoreLock.writeLock().unlock();
723 boolean coreIsOpen() {
724 currentCoreLock.readLock().lock();
726 return (null != currentCore);
728 currentCoreLock.readLock().unlock();
732 Index getIndexInfo() throws NoOpenCoreException {
733 currentCoreLock.readLock().lock();
735 if (null == currentCore) {
736 throw new NoOpenCoreException();
738 return currentCore.getIndexInfo();
740 currentCoreLock.readLock().unlock();
744 void closeCore() throws KeywordSearchModuleException {
745 currentCoreLock.writeLock().lock();
747 if (null != currentCore) {
750 serverAction.putValue(CORE_EVT, CORE_EVT_STATES.STOPPED);
753 currentCoreLock.writeLock().unlock();
757 void addDocument(SolrInputDocument doc)
throws KeywordSearchModuleException, NoOpenCoreException {
758 currentCoreLock.readLock().lock();
760 if (null == currentCore) {
761 throw new NoOpenCoreException();
763 TimingMetric metric = HealthMonitor.getTimingMetric(
"Solr: Index chunk");
764 currentCore.addDocument(doc);
765 HealthMonitor.submitTimingMetric(metric);
767 currentCoreLock.readLock().unlock();
780 "# {0} - core name",
"Server.deleteCore.exception.msg=Failed to delete Solr core {0}",})
781 void deleteCore(String coreName, CaseMetadata metadata)
throws KeywordSearchServiceException {
783 HttpSolrServer solrServer;
784 if (metadata.getCaseType() == CaseType.SINGLE_USER_CASE) {
785 Integer localSolrServerPort = Integer.decode(ModuleSettings.getConfigSetting(PROPERTIES_FILE, PROPERTIES_CURRENT_SERVER_PORT));
786 solrServer =
new HttpSolrServer(
"http://localhost:" + localSolrServerPort +
"/solr");
789 solrServer =
new HttpSolrServer(
"http://" + properties.getHost() +
":" + properties.getPort() +
"/solr");
791 connectToSolrServer(solrServer);
792 CoreAdminResponse response = CoreAdminRequest.getStatus(coreName, solrServer);
793 if (null != response.getCoreStatus(coreName).get(
"instanceDir")) {
803 org.apache.solr.client.solrj.request.CoreAdminRequest.unloadCore(coreName,
true,
true, solrServer);
805 }
catch (SolrServerException | HttpSolrServer.RemoteSolrException | IOException ex) {
808 if (!ex.getMessage().equals(
"Already closed")) {
809 throw new KeywordSearchServiceException(Bundle.Server_deleteCore_exception_msg(coreName), ex);
825 private Core
openCore(
Case theCase, Index index)
throws KeywordSearchModuleException {
832 currentSolrServer =
new HttpSolrServer(
"http://" + properties.
getHost() +
":" + properties.
getPort() +
"/solr");
835 connectToSolrServer(currentSolrServer);
838 }
catch (SolrServerException | IOException ex) {
839 throw new KeywordSearchModuleException(NbBundle.getMessage(
Server.class,
"Server.connect.exception.msg", ex.getLocalizedMessage()), ex);
843 File dataDir =
new File(
new File(index.getIndexPath()).getParent());
844 if (!dataDir.exists()) {
848 if (!this.isRunning()) {
849 logger.log(Level.SEVERE,
"Core create/open requested, but server not yet running");
850 throw new KeywordSearchModuleException(NbBundle.getMessage(
this.getClass(),
"Server.openCore.exception.msg"));
853 String coreName = index.getIndexName();
864 Path corePropertiesFile = Paths.get(solrFolder.toString(),
SOLR, coreName,
CORE_PROPERTIES);
865 if (corePropertiesFile.toFile().exists()) {
867 corePropertiesFile.toFile().delete();
868 }
catch (Exception ex) {
869 logger.log(Level.INFO,
"Could not delete pre-existing core.properties prior to opening the core.");
874 CoreAdminRequest.Create createCoreRequest =
new CoreAdminRequest.Create();
875 createCoreRequest.setDataDir(dataDir.getAbsolutePath());
876 createCoreRequest.setCoreName(coreName);
877 createCoreRequest.setConfigSet(
"AutopsyConfig");
878 createCoreRequest.setIsLoadOnStartup(
false);
879 createCoreRequest.setIsTransient(
true);
880 currentSolrServer.request(createCoreRequest);
884 throw new KeywordSearchModuleException(NbBundle.getMessage(
this.getClass(),
"Server.openCore.exception.noIndexDir.msg"));
887 return new Core(coreName, theCase.getCaseType(), index);
889 }
catch (Exception ex) {
890 throw new KeywordSearchModuleException(NbBundle.getMessage(
this.getClass(),
"Server.openCore.exception.cantOpen.msg"), ex);
906 Path serverFilePath = Paths.get(caseDirectory,
"solrserver.txt");
907 if (serverFilePath.toFile().exists()) {
909 List<String> lines = Files.readAllLines(serverFilePath);
910 if (lines.isEmpty()) {
911 logger.log(Level.SEVERE,
"solrserver.txt file does not contain any data");
912 }
else if (!lines.get(0).contains(
",")) {
913 logger.log(Level.SEVERE,
"solrserver.txt file is corrupt - could not read host/port from " + lines.get(0));
915 String[] parts = lines.get(0).split(
",");
916 if (parts.length != 2) {
917 logger.log(Level.SEVERE,
"solrserver.txt file is corrupt - could not read host/port from " + lines.get(0));
922 }
catch (IOException ex) {
923 logger.log(Level.SEVERE,
"solrserver.txt file could not be read", ex);
945 public static void selectSolrServerForCase(Path rootOutputDirectory, Path caseDirectoryPath)
throws KeywordSearchModuleException {
947 String serverListName =
"solrServerList.txt";
948 Path serverListPath = Paths.get(rootOutputDirectory.toString(), serverListName);
949 if (serverListPath.toFile().exists()) {
954 lines = Files.readAllLines(serverListPath);
955 }
catch (IOException ex) {
956 throw new KeywordSearchModuleException(serverListName +
" could not be read", ex);
960 for (Iterator<String> iterator = lines.iterator(); iterator.hasNext();) {
961 String line = iterator.next();
962 if (!line.contains(
",")) {
967 if (lines.isEmpty()) {
968 throw new KeywordSearchModuleException(serverListName +
" had no valid server information");
972 int rnd =
new Random().nextInt(lines.size());
973 String[] parts = lines.get(rnd).split(
",");
974 if (parts.length != 2) {
975 throw new KeywordSearchModuleException(
"Invalid server data: " + lines.get(rnd));
979 String host = parts[0];
980 String port = parts[1];
981 if (host.isEmpty() || port.isEmpty()) {
982 throw new KeywordSearchModuleException(
"Invalid server data: " + lines.get(rnd));
986 Path serverFile = Paths.get(caseDirectoryPath.toString(),
"solrserver.txt");
988 caseDirectoryPath.toFile().mkdirs();
989 if (!caseDirectoryPath.toFile().exists()) {
990 throw new KeywordSearchModuleException(
"Case directory " + caseDirectoryPath.toString() +
" does not exist");
992 Files.write(serverFile, lines.get(rnd).getBytes());
993 }
catch (IOException ex) {
994 throw new KeywordSearchModuleException(serverFile.toString() +
" could not be written", ex);
1036 void commit() throws SolrServerException, NoOpenCoreException {
1037 currentCoreLock.readLock().lock();
1039 if (null == currentCore) {
1040 throw new NoOpenCoreException();
1042 currentCore.commit();
1044 currentCoreLock.readLock().unlock();
1048 NamedList<Object> request(SolrRequest request)
throws SolrServerException, NoOpenCoreException {
1049 currentCoreLock.readLock().lock();
1051 if (null == currentCore) {
1052 throw new NoOpenCoreException();
1054 return currentCore.request(request);
1056 currentCoreLock.readLock().unlock();
1071 currentCoreLock.readLock().lock();
1073 if (null == currentCore) {
1074 throw new NoOpenCoreException();
1077 return currentCore.queryNumIndexedFiles();
1078 }
catch (SolrServerException | IOException ex) {
1079 throw new KeywordSearchModuleException(NbBundle.getMessage(
this.getClass(),
"Server.queryNumIdxFiles.exception.msg"), ex);
1082 currentCoreLock.readLock().unlock();
1096 currentCoreLock.readLock().lock();
1098 if (null == currentCore) {
1099 throw new NoOpenCoreException();
1102 return currentCore.queryNumIndexedChunks();
1103 }
catch (SolrServerException | IOException ex) {
1104 throw new KeywordSearchModuleException(NbBundle.getMessage(
this.getClass(),
"Server.queryNumIdxChunks.exception.msg"), ex);
1107 currentCoreLock.readLock().unlock();
1121 currentCoreLock.readLock().lock();
1123 if (null == currentCore) {
1124 throw new NoOpenCoreException();
1127 return currentCore.queryNumIndexedDocuments();
1128 }
catch (SolrServerException | IOException ex) {
1129 throw new KeywordSearchModuleException(NbBundle.getMessage(
this.getClass(),
"Server.queryNumIdxDocs.exception.msg"), ex);
1132 currentCoreLock.readLock().unlock();
1146 public boolean queryIsIndexed(
long contentID)
throws KeywordSearchModuleException, NoOpenCoreException {
1147 currentCoreLock.readLock().lock();
1149 if (null == currentCore) {
1150 throw new NoOpenCoreException();
1153 return currentCore.queryIsIndexed(contentID);
1154 }
catch (SolrServerException | IOException ex) {
1155 throw new KeywordSearchModuleException(NbBundle.getMessage(
this.getClass(),
"Server.queryIsIdxd.exception.msg"), ex);
1159 currentCoreLock.readLock().unlock();
1175 currentCoreLock.readLock().lock();
1177 if (null == currentCore) {
1178 throw new NoOpenCoreException();
1181 return currentCore.queryNumFileChunks(fileID);
1182 }
catch (SolrServerException | IOException ex) {
1183 throw new KeywordSearchModuleException(NbBundle.getMessage(
this.getClass(),
"Server.queryNumFileChunks.exception.msg"), ex);
1186 currentCoreLock.readLock().unlock();
1200 public QueryResponse
query(SolrQuery sq)
throws KeywordSearchModuleException, NoOpenCoreException, IOException {
1201 currentCoreLock.readLock().lock();
1203 if (null == currentCore) {
1204 throw new NoOpenCoreException();
1207 return currentCore.query(sq);
1208 }
catch (SolrServerException ex) {
1209 logger.log(Level.SEVERE,
"Solr query failed: " + sq.getQuery(), ex);
1210 throw new KeywordSearchModuleException(NbBundle.getMessage(
this.getClass(),
"Server.query.exception.msg", sq.getQuery()), ex);
1213 currentCoreLock.readLock().unlock();
1228 public QueryResponse
query(SolrQuery sq, SolrRequest.METHOD method) throws KeywordSearchModuleException, NoOpenCoreException {
1229 currentCoreLock.readLock().lock();
1231 if (null == currentCore) {
1232 throw new NoOpenCoreException();
1235 return currentCore.query(sq, method);
1236 }
catch (SolrServerException | IOException ex) {
1237 logger.log(Level.SEVERE,
"Solr query failed: " + sq.getQuery(), ex);
1238 throw new KeywordSearchModuleException(NbBundle.getMessage(
this.getClass(),
"Server.query2.exception.msg", sq.getQuery()), ex);
1241 currentCoreLock.readLock().unlock();
1255 public TermsResponse
queryTerms(SolrQuery sq)
throws KeywordSearchModuleException, NoOpenCoreException {
1256 currentCoreLock.readLock().lock();
1258 if (null == currentCore) {
1259 throw new NoOpenCoreException();
1262 return currentCore.queryTerms(sq);
1263 }
catch (SolrServerException | IOException ex) {
1264 logger.log(Level.SEVERE,
"Solr terms query failed: " + sq.getQuery(), ex);
1265 throw new KeywordSearchModuleException(NbBundle.getMessage(
this.getClass(),
"Server.queryTerms.exception.msg", sq.getQuery()), ex);
1268 currentCoreLock.readLock().unlock();
1279 void deleteDataSource(Long dataSourceId)
throws IOException, KeywordSearchModuleException, NoOpenCoreException, SolrServerException {
1281 currentCoreLock.writeLock().lock();
1282 if (null == currentCore) {
1283 throw new NoOpenCoreException();
1285 currentCore.deleteDataSource(dataSourceId);
1286 currentCore.commit();
1288 currentCoreLock.writeLock().unlock();
1302 currentCoreLock.readLock().lock();
1304 if (null == currentCore) {
1305 throw new NoOpenCoreException();
1307 return currentCore.getSolrContent(content.getId(), 0);
1309 currentCoreLock.readLock().unlock();
1325 public String
getSolrContent(
final Content content,
int chunkID)
throws NoOpenCoreException {
1326 currentCoreLock.readLock().lock();
1328 if (null == currentCore) {
1329 throw new NoOpenCoreException();
1331 return currentCore.getSolrContent(content.getId(), chunkID);
1333 currentCoreLock.readLock().unlock();
1347 currentCoreLock.readLock().lock();
1349 if (null == currentCore) {
1350 throw new NoOpenCoreException();
1352 return currentCore.getSolrContent(objectID, 0);
1354 currentCoreLock.readLock().unlock();
1368 public String
getSolrContent(
final long objectID,
final int chunkID)
throws NoOpenCoreException {
1369 currentCoreLock.readLock().lock();
1371 if (null == currentCore) {
1372 throw new NoOpenCoreException();
1374 return currentCore.getSolrContent(objectID, chunkID);
1376 currentCoreLock.readLock().unlock();
1401 void connectToSolrServer(HttpSolrServer solrServer)
throws SolrServerException, IOException {
1403 CoreAdminRequest statusRequest =
new CoreAdminRequest();
1404 statusRequest.setCoreName(null);
1405 statusRequest.setAction(CoreAdminParams.CoreAdminAction.STATUS);
1406 statusRequest.setIndexInfoNeeded(
false);
1407 statusRequest.process(solrServer);
1424 private boolean coreIsLoaded(String coreName)
throws SolrServerException, IOException {
1425 CoreAdminResponse response = CoreAdminRequest.getStatus(coreName, currentSolrServer);
1426 return response.getCoreStatus(coreName).get(
"instanceDir") != null;
1440 CoreAdminResponse response = CoreAdminRequest.getStatus(coreName, currentSolrServer);
1441 Object dataDirPath = response.getCoreStatus(coreName).get(
"dataDir");
1442 if (null != dataDirPath) {
1443 File indexDir = Paths.get((String) dataDirPath,
"index").toFile();
1444 return indexDir.exists();
1453 private final String name;
1457 private final Index textIndex;
1461 private final HttpSolrServer solrCore;
1463 private final int QUERY_TIMEOUT_MILLISECONDS = 86400000;
1465 private Core(String name,
CaseType caseType, Index index) {
1467 this.caseType = caseType;
1468 this.textIndex = index;
1470 this.solrCore =
new HttpSolrServer(currentSolrServer.getBaseURL() +
"/" + name);
1474 solrCore.setSoTimeout(QUERY_TIMEOUT_MILLISECONDS);
1476 solrCore.setDefaultMaxConnectionsPerHost(32);
1477 solrCore.setMaxTotalConnections(32);
1478 solrCore.setFollowRedirects(
false);
1481 solrCore.setAllowCompression(
true);
1482 solrCore.setParser(
new XMLResponseParser());
1495 private Index getIndexInfo() {
1496 return this.textIndex;
1499 private QueryResponse
query(SolrQuery sq)
throws SolrServerException, IOException {
1500 return solrCore.query(sq);
1503 private NamedList<Object> request(SolrRequest request)
throws SolrServerException {
1505 return solrCore.request(request);
1506 }
catch (IOException e) {
1507 logger.log(Level.WARNING,
"Could not issue Solr request. ", e);
1508 throw new SolrServerException(
1509 NbBundle.getMessage(
this.getClass(),
"Server.request.exception.exception.msg"), e);
1514 private QueryResponse
query(SolrQuery sq, SolrRequest.METHOD method) throws SolrServerException, IOException {
1515 return solrCore.query(sq, method);
1518 private TermsResponse
queryTerms(SolrQuery sq)
throws SolrServerException, IOException {
1519 QueryResponse qres = solrCore.query(sq);
1520 return qres.getTermsResponse();
1523 private void commit() throws SolrServerException {
1526 solrCore.commit(
true,
true);
1527 }
catch (IOException e) {
1528 logger.log(Level.WARNING,
"Could not commit index. ", e);
1529 throw new SolrServerException(NbBundle.getMessage(
this.getClass(),
"Server.commit.exception.msg"), e);
1533 private void deleteDataSource(Long dsObjId)
throws IOException, SolrServerException {
1534 String dataSourceId = Long.toString(dsObjId);
1535 String deleteQuery =
"image_id:" + dataSourceId;
1537 solrCore.deleteByQuery(deleteQuery);
1540 void addDocument(SolrInputDocument doc)
throws KeywordSearchModuleException {
1543 }
catch (SolrServerException ex) {
1544 logger.log(Level.SEVERE,
"Could not add document to index via update handler: " + doc.getField(
"id"), ex);
1545 throw new KeywordSearchModuleException(
1546 NbBundle.getMessage(
this.getClass(),
"Server.addDoc.exception.msg", doc.getField(
"id")), ex);
1547 }
catch (IOException ex) {
1548 logger.log(Level.SEVERE,
"Could not add document to index via update handler: " + doc.getField(
"id"), ex);
1549 throw new KeywordSearchModuleException(
1550 NbBundle.getMessage(
this.getClass(),
"Server.addDoc.exception.msg2", doc.getField(
"id")), ex);
1565 final SolrQuery q =
new SolrQuery();
1567 String filterQuery = Schema.ID.toString() +
":" + KeywordSearchUtil.escapeLuceneQuery(Long.toString(contentID));
1569 filterQuery = filterQuery + Server.CHUNK_ID_SEPARATOR + chunkID;
1571 q.addFilterQuery(filterQuery);
1572 q.setFields(Schema.TEXT.toString());
1575 SolrDocumentList solrDocuments = solrCore.query(q).getResults();
1577 if (!solrDocuments.isEmpty()) {
1578 SolrDocument solrDocument = solrDocuments.get(0);
1579 if (solrDocument != null) {
1580 Collection<Object> fieldValues = solrDocument.getFieldValues(Schema.TEXT.toString());
1581 if (fieldValues.size() == 1)
1583 return fieldValues.toArray(
new String[0])[0];
1587 return fieldValues.toArray(
new String[0])[1];
1591 }
catch (SolrServerException ex) {
1592 logger.log(Level.SEVERE,
"Error getting content from Solr. Solr document id " + contentID +
", chunk id " + chunkID +
", query: " + filterQuery, ex);
1599 synchronized void close() throws KeywordSearchModuleException {
1606 CoreAdminRequest.unloadCore(this.name, currentSolrServer);
1607 }
catch (SolrServerException ex) {
1608 throw new KeywordSearchModuleException(
1609 NbBundle.getMessage(
this.getClass(),
"Server.close.exception.msg"), ex);
1610 }
catch (IOException ex) {
1611 throw new KeywordSearchModuleException(
1612 NbBundle.getMessage(
this.getClass(),
"Server.close.exception.msg2"), ex);
1639 SolrQuery q =
new SolrQuery(Server.Schema.ID +
":*" + Server.CHUNK_ID_SEPARATOR +
"*");
1641 int numChunks = (int)
query(q).getResults().getNumFound();
1656 SolrQuery q =
new SolrQuery(
"*:*");
1658 return (
int)
query(q).getResults().getNumFound();
1670 private boolean queryIsIndexed(
long contentID)
throws SolrServerException, IOException {
1671 String
id = KeywordSearchUtil.escapeLuceneQuery(Long.toString(contentID));
1672 SolrQuery q =
new SolrQuery(
"*:*");
1673 q.addFilterQuery(Server.Schema.ID.toString() +
":" + id);
1676 return (
int)
query(q).getResults().getNumFound() != 0;
1690 private int queryNumFileChunks(
long contentID)
throws SolrServerException, IOException {
1691 String
id = KeywordSearchUtil.escapeLuceneQuery(Long.toString(contentID));
1693 =
new SolrQuery(Server.Schema.ID +
":" +
id + Server.CHUNK_ID_SEPARATOR +
"*");
1695 return (
int)
query(q).getResults().getNumFound();
1699 class ServerAction
extends AbstractAction {
1701 private static final long serialVersionUID = 1L;
1704 public void actionPerformed(ActionEvent e) {
1705 logger.log(Level.INFO, e.paramString().trim());
1712 class SolrServerNoPortException
extends SocketException {
1714 private static final long serialVersionUID = 1L;
1719 private final int port;
1721 SolrServerNoPortException(
int port) {
1722 super(NbBundle.getMessage(Server.class,
"Server.solrServerNoPortException.msg", port,
1723 Server.PROPERTIES_CURRENT_SERVER_PORT));
1727 int getPortNumber() {
static synchronized String getConfigSetting(String moduleName, String settingName)
int queryNumIndexedFiles()
String getSolrContent(final long objectID)
final ReentrantReadWriteLock currentCoreLock
int queryNumIndexedChunks()
static final char ID_CHUNK_SEP
final ServerAction serverAction
static String getIndexingServerPort()
static IndexingServerProperties getMultiUserServerProperties(String caseDirectory)
static final String CORE_PROPERTIES
boolean coreIsLoaded(String coreName)
final HttpSolrServer localSolrServer
static final Logger logger
static TimingMetric getTimingMetric(String name)
static int getMaxSolrVMSize()
static void selectSolrServerForCase(Path rootOutputDirectory, Path caseDirectoryPath)
void addServerActionListener(PropertyChangeListener l)
static synchronized boolean settingExists(String moduleName, String settingName)
static final String HL_ANALYZE_CHARS_UNLIMITED
Process runSolrCommand(List< String > solrArguments)
String getSolrContent(final Content content)
static final long MAX_CONTENT_SIZE
boolean coreIndexFolderExists(String coreName)
HttpSolrServer currentSolrServer
int queryNumIndexedDocuments()
static synchronized void setConfigSetting(String moduleName, String settingName, String settingVal)
static final String CHUNK_ID_SEPARATOR
static final String CORE_EVT
static final Charset DEFAULT_INDEXED_TEXT_CHARSET
default Charset to index text as
InputStreamPrinterThread errorRedirectThread
QueryResponse query(SolrQuery sq)
static void submitTimingMetric(TimingMetric metric)
int currentSolrServerPort
TermsResponse queryTerms(SolrQuery sq)
boolean queryIsIndexed(long contentID)
String getSolrContent(final Content content, int chunkID)
String getSolrContent(final long objectID, final int chunkID)
synchronized static Logger getLogger(String name)
Core openCore(Case theCase, Index index)
static String getChunkIdString(long parentID, int childID)
static String getIndexingServerHost()
int queryNumFileChunks(long fileID)
static final boolean DEBUG
QueryResponse query(SolrQuery sq, SolrRequest.METHOD method)