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() {
142 public String toString() {
149 public String toString() {
156 public String toString() {
163 public String toString() {
169 public String toString() {
175 public String toString() {
192 static final String PROPERTIES_FILE = KeywordSearchSettings.MODULE_NAME;
193 static final String PROPERTIES_CURRENT_SERVER_PORT =
"IndexingServerPort";
194 static final String PROPERTIES_CURRENT_STOP_PORT =
"IndexingServerStopPort";
195 private static final String
KEY =
"jjk#09s";
196 static final String DEFAULT_SOLR_SERVER_HOST =
"localhost";
197 static final int DEFAULT_SOLR_SERVER_PORT = 23232;
198 static final int DEFAULT_SOLR_STOP_PORT = 34343;
201 private static final boolean DEBUG =
false;
202 private static final String
SOLR =
"solr";
232 this.localSolrServer =
new HttpSolrServer(
"http://localhost:" + currentSolrServerPort +
"/solr");
233 serverAction =
new ServerAction();
234 solrFolder = InstalledFileLocator.getDefault().locate(
"solr",
Server.class.getPackage().getName(),
false);
238 if (!solrHome.toFile().exists()) {
240 Files.createDirectory(solrHome);
241 Files.copy(Paths.get(solrFolder.getAbsolutePath(),
"solr",
"solr.xml"), solrHome.resolve(
"solr.xml"));
242 Files.copy(Paths.get(solrFolder.getAbsolutePath(),
"solr",
"zoo.cfg"), solrHome.resolve(
"zoo.cfg"));
243 }
catch (IOException ex) {
244 logger.log(Level.SEVERE,
"Failed to create Solr home folder:", ex);
247 currentCoreLock =
new ReentrantReadWriteLock(
true);
249 logger.log(Level.INFO,
"Created Server instance using Java at {0}", javaPath);
257 }
catch (NumberFormatException nfe) {
258 logger.log(Level.WARNING,
"Could not decode indexing server port, value was not a valid port number, using the default. ", nfe);
259 currentSolrServerPort = DEFAULT_SOLR_SERVER_PORT;
262 currentSolrServerPort = DEFAULT_SOLR_SERVER_PORT;
269 }
catch (NumberFormatException nfe) {
270 logger.log(Level.WARNING,
"Could not decode indexing server stop port, value was not a valid port number, using default", nfe);
271 currentSolrStopPort = DEFAULT_SOLR_STOP_PORT;
274 currentSolrStopPort = DEFAULT_SOLR_STOP_PORT;
280 public void finalize() throws java.lang.Throwable {
286 serverAction.addPropertyChangeListener(l);
289 int getCurrentSolrServerPort() {
293 int getCurrentSolrStopPort() {
304 volatile boolean doRun =
true;
307 this.stream = stream;
309 final String log = Places.getUserDirectory().getAbsolutePath()
310 + File.separator +
"var" + File.separator +
"log"
311 + File.separator +
"solr.log." + type;
312 File outputFile =
new File(log.concat(
".0"));
313 File first =
new File(log.concat(
".1"));
314 File second =
new File(log.concat(
".2"));
315 if (second.exists()) {
318 if (first.exists()) {
319 first.renameTo(second);
321 if (outputFile.exists()) {
322 outputFile.renameTo(first);
324 outputFile.createNewFile();
326 out =
new FileOutputStream(outputFile);
328 }
catch (Exception ex) {
329 logger.log(Level.WARNING,
"Failed to create solr log file", ex);
340 try (InputStreamReader isr =
new InputStreamReader(stream);
341 BufferedReader br =
new BufferedReader(isr);
343 BufferedWriter bw =
new BufferedWriter(osw);) {
346 while (doRun && (line = br.readLine()) != null) {
355 }
catch (IOException ex) {
356 logger.log(Level.SEVERE,
"Error redirecting Solr output stream", ex);
373 List<String> commandLine =
new ArrayList<>();
374 commandLine.add(javaPath);
375 commandLine.add(MAX_SOLR_MEM_MB_PAR);
376 commandLine.add(
"-DSTOP.PORT=" + currentSolrStopPort);
377 commandLine.add(
"-Djetty.port=" + currentSolrServerPort);
378 commandLine.add(
"-DSTOP.KEY=" + KEY);
379 commandLine.add(
"-jar");
380 commandLine.add(
"start.jar");
382 commandLine.addAll(solrArguments);
384 ProcessBuilder solrProcessBuilder =
new ProcessBuilder(commandLine);
385 solrProcessBuilder.directory(solrFolder);
388 Path solrStdoutPath = Paths.get(Places.getUserDirectory().getAbsolutePath(),
"var",
"log",
"solr.log.stdout");
389 solrProcessBuilder.redirectOutput(solrStdoutPath.toFile());
391 Path solrStderrPath = Paths.get(Places.getUserDirectory().getAbsolutePath(),
"var",
"log",
"solr.log.stderr");
392 solrProcessBuilder.redirectError(solrStderrPath.toFile());
394 logger.log(Level.INFO,
"Running Solr command: {0}", solrProcessBuilder.command());
395 Process process = solrProcessBuilder.start();
396 logger.log(Level.INFO,
"Finished running Solr command");
405 List<Long> getSolrPIDs() {
406 List<Long> pids =
new ArrayList<>();
409 final String pidsQuery =
"Args.*.eq=-DSTOP.KEY=" + KEY +
",Args.*.eq=start.jar";
412 if (pidsArr != null) {
413 for (
int i = 0; i < pidsArr.length; ++i) {
414 pids.add(pidsArr[i]);
426 List<Long> solrPids = getSolrPIDs();
427 for (
long pid : solrPids) {
428 logger.log(Level.INFO,
"Trying to kill old Solr process, PID: {0}", pid);
429 PlatformUtil.killProcess(pid);
439 "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.",})
440 void start()
throws KeywordSearchModuleException, SolrServerNoPortException {
446 if (!isPortAvailable(currentSolrServerPort)) {
450 final List<Long> pids = this.getSolrPIDs();
454 if (pids.isEmpty()) {
455 throw new SolrServerNoPortException(currentSolrServerPort);
464 if (!isPortAvailable(currentSolrServerPort)) {
465 throw new SolrServerNoPortException(currentSolrServerPort);
467 if (!isPortAvailable(currentSolrStopPort)) {
468 throw new SolrServerNoPortException(currentSolrStopPort);
472 logger.log(Level.INFO,
"Starting Solr server from: {0}", solrFolder.getAbsolutePath());
474 if (isPortAvailable(currentSolrServerPort)) {
475 logger.log(Level.INFO,
"Port [{0}] available, starting Solr", currentSolrServerPort);
478 Arrays.asList(
"-Dbootstrap_confdir=../solr/configsets/AutopsyConfig/conf",
479 "-Dcollection.configName=AutopsyConfig")));
482 for (
int numRetries = 0; numRetries < 6; numRetries++) {
484 final List<Long> pids = this.getSolrPIDs();
485 logger.log(Level.INFO,
"New Solr process PID: {0}", pids);
492 TimeUnit.SECONDS.sleep(5);
493 }
catch (InterruptedException ex) {
494 logger.log(Level.WARNING,
"Timer interrupted");
500 logger.log(Level.WARNING,
"Local Solr server failed to respond to status requests.");
501 WindowManager.getDefault().invokeWhenUIReady(
new Runnable() {
504 MessageNotifyUtil.Notify.error(
505 NbBundle.getMessage(
this.getClass(),
"Installer.errorInitKsmMsg"),
506 Bundle.Server_status_failed_msg());
509 }
catch (SecurityException ex) {
510 logger.log(Level.SEVERE,
"Could not start Solr process!", ex);
511 throw new KeywordSearchModuleException(
512 NbBundle.getMessage(
this.getClass(),
"Server.start.exception.cantStartSolr.msg"), ex);
513 }
catch (IOException ex) {
514 logger.log(Level.SEVERE,
"Could not start Solr server process!", ex);
515 throw new KeywordSearchModuleException(
516 NbBundle.getMessage(
this.getClass(),
"Server.start.exception.cantStartSolr.msg2"), ex);
526 static boolean isPortAvailable(
int port) {
527 ServerSocket ss = null;
530 ss =
new ServerSocket(port, 0, java.net.Inet4Address.getByName(
"localhost"));
532 ss.setReuseAddress(
true);
537 }
catch (IOException e) {
542 }
catch (IOException e) {
557 void changeSolrServerPort(
int port) {
558 currentSolrServerPort = port;
559 ModuleSettings.setConfigSetting(PROPERTIES_FILE, PROPERTIES_CURRENT_SERVER_PORT, String.valueOf(port));
567 void changeSolrStopPort(
int port) {
568 currentSolrStopPort = port;
569 ModuleSettings.setConfigSetting(PROPERTIES_FILE, PROPERTIES_CURRENT_STOP_PORT, String.valueOf(port));
577 synchronized void stop() {
582 }
catch (KeywordSearchModuleException e) {
583 logger.log(Level.WARNING,
"Failed to close core: ", e);
587 logger.log(Level.INFO,
"Stopping Solr server from: {0}", solrFolder.getAbsolutePath());
590 Process process =
runSolrCommand(
new ArrayList<>(Arrays.asList(
"--stop")));
592 logger.log(Level.INFO,
"Waiting for Solr server to stop");
596 if (curSolrProcess != null) {
597 curSolrProcess.destroy();
598 curSolrProcess = null;
601 }
catch (IOException | InterruptedException ex) {
602 logger.log(Level.WARNING,
"Error while attempting to stop Solr server", ex);
606 if (errorRedirectThread != null) {
607 errorRedirectThread.stopRun();
608 errorRedirectThread = null;
615 logger.log(Level.INFO,
"Finished stopping Solr server");
626 synchronized boolean isRunning() throws KeywordSearchModuleException {
629 if (isPortAvailable(currentSolrServerPort)) {
636 connectToSolrServer(localSolrServer);
638 logger.log(Level.INFO,
"Solr server is running");
639 }
catch (SolrServerException ex) {
641 Throwable cause = ex.getRootCause();
646 if (cause instanceof ConnectException || cause instanceof SocketException) {
647 logger.log(Level.INFO,
"Solr server is not running, cause: {0}", cause.getMessage());
650 throw new KeywordSearchModuleException(
651 NbBundle.getMessage(
this.getClass(),
"Server.isRunning.exception.errCheckSolrRunning.msg"), ex);
653 }
catch (SolrException ex) {
655 logger.log(Level.INFO,
"Solr server is not running", ex);
657 }
catch (IOException ex) {
658 throw new KeywordSearchModuleException(
659 NbBundle.getMessage(
this.getClass(),
"Server.isRunning.exception.errCheckSolrRunning.msg2"), ex);
677 void openCoreForCase(Case theCase, Index index)
throws KeywordSearchModuleException {
678 currentCoreLock.writeLock().lock();
680 currentCore =
openCore(theCase, index);
685 }
catch (NoOpenCoreException ex) {
686 throw new KeywordSearchModuleException(NbBundle.getMessage(
this.getClass(),
"Server.openCore.exception.cantOpen.msg"), ex);
689 serverAction.putValue(CORE_EVT, CORE_EVT_STATES.STARTED);
691 currentCoreLock.writeLock().unlock();
700 boolean coreIsOpen() {
701 currentCoreLock.readLock().lock();
703 return (null != currentCore);
705 currentCoreLock.readLock().unlock();
709 Index getIndexInfo() throws NoOpenCoreException {
710 currentCoreLock.readLock().lock();
712 if (null == currentCore) {
713 throw new NoOpenCoreException();
715 return currentCore.getIndexInfo();
717 currentCoreLock.readLock().unlock();
721 void closeCore() throws KeywordSearchModuleException {
722 currentCoreLock.writeLock().lock();
724 if (null != currentCore) {
727 serverAction.putValue(CORE_EVT, CORE_EVT_STATES.STOPPED);
730 currentCoreLock.writeLock().unlock();
734 void addDocument(SolrInputDocument doc)
throws KeywordSearchModuleException, NoOpenCoreException {
735 currentCoreLock.readLock().lock();
737 if (null == currentCore) {
738 throw new NoOpenCoreException();
740 TimingMetric metric = HealthMonitor.getTimingMetric(
"Solr: Index chunk");
741 currentCore.addDocument(doc);
742 HealthMonitor.submitTimingMetric(metric);
744 currentCoreLock.readLock().unlock();
757 "# {0} - core name",
"Server.deleteCore.exception.msg=Failed to delete Solr core {0}",})
758 void deleteCore(String coreName, CaseMetadata metadata)
throws KeywordSearchServiceException {
760 HttpSolrServer solrServer;
761 if (metadata.getCaseType() == CaseType.SINGLE_USER_CASE) {
762 Integer localSolrServerPort = Integer.decode(ModuleSettings.getConfigSetting(PROPERTIES_FILE, PROPERTIES_CURRENT_SERVER_PORT));
763 solrServer =
new HttpSolrServer(
"http://localhost:" + localSolrServerPort +
"/solr");
766 solrServer =
new HttpSolrServer(
"http://" + properties.getHost() +
":" + properties.getPort() +
"/solr");
768 connectToSolrServer(solrServer);
769 CoreAdminResponse response = CoreAdminRequest.getStatus(coreName, solrServer);
770 if (null != response.getCoreStatus(coreName).get(
"instanceDir")) {
780 org.apache.solr.client.solrj.request.CoreAdminRequest.unloadCore(coreName,
true,
true, solrServer);
782 }
catch (SolrServerException | HttpSolrServer.RemoteSolrException | IOException ex) {
785 if (!ex.getMessage().equals(
"Already closed")) {
786 throw new KeywordSearchServiceException(Bundle.Server_deleteCore_exception_msg(coreName), ex);
802 private Core
openCore(
Case theCase, Index index)
throws KeywordSearchModuleException {
809 currentSolrServer =
new HttpSolrServer(
"http://" + properties.
getHost() +
":" + properties.
getPort() +
"/solr");
812 connectToSolrServer(currentSolrServer);
815 }
catch (SolrServerException | IOException ex) {
816 throw new KeywordSearchModuleException(NbBundle.getMessage(
Server.class,
"Server.connect.exception.msg", ex.getLocalizedMessage()), ex);
820 File dataDir =
new File(
new File(index.getIndexPath()).getParent());
821 if (!dataDir.exists()) {
825 if (!this.isRunning()) {
826 logger.log(Level.SEVERE,
"Core create/open requested, but server not yet running");
827 throw new KeywordSearchModuleException(NbBundle.getMessage(
this.getClass(),
"Server.openCore.exception.msg"));
830 String coreName = index.getIndexName();
841 Path corePropertiesFile = Paths.get(solrFolder.toString(),
SOLR, coreName,
CORE_PROPERTIES);
842 if (corePropertiesFile.toFile().exists()) {
844 corePropertiesFile.toFile().delete();
845 }
catch (Exception ex) {
846 logger.log(Level.INFO,
"Could not delete pre-existing core.properties prior to opening the core.");
851 CoreAdminRequest.Create createCoreRequest =
new CoreAdminRequest.Create();
852 createCoreRequest.setDataDir(dataDir.getAbsolutePath());
853 createCoreRequest.setCoreName(coreName);
854 createCoreRequest.setConfigSet(
"AutopsyConfig");
855 createCoreRequest.setIsLoadOnStartup(
false);
856 createCoreRequest.setIsTransient(
true);
857 currentSolrServer.request(createCoreRequest);
861 throw new KeywordSearchModuleException(NbBundle.getMessage(
this.getClass(),
"Server.openCore.exception.noIndexDir.msg"));
864 return new Core(coreName, theCase.getCaseType(), index);
866 }
catch (Exception ex) {
867 throw new KeywordSearchModuleException(NbBundle.getMessage(
this.getClass(),
"Server.openCore.exception.cantOpen.msg"), ex);
881 Path serverFilePath = Paths.get(caseDirectory,
"solrserver.txt");
882 if(serverFilePath.toFile().exists()){
884 List<String> lines = Files.readAllLines(serverFilePath);
885 if(lines.isEmpty()) {
886 logger.log(Level.SEVERE,
"solrserver.txt file does not contain any data");
887 }
else if (! lines.get(0).contains(
",")) {
888 logger.log(Level.SEVERE,
"solrserver.txt file is corrupt - could not read host/port from " + lines.get(0));
890 String[] parts = lines.get(0).split(
",");
891 if(parts.length != 2) {
892 logger.log(Level.SEVERE,
"solrserver.txt file is corrupt - could not read host/port from " + lines.get(0));
897 }
catch (IOException ex) {
898 logger.log(Level.SEVERE,
"solrserver.txt file could not be read", ex);
921 public static void selectSolrServerForCase(Path rootOutputDirectory, Path caseDirectoryPath)
throws KeywordSearchModuleException {
923 String serverListName =
"solrServerList.txt";
924 Path serverListPath = Paths.get(rootOutputDirectory.toString(), serverListName);
925 if(serverListPath.toFile().exists()){
930 lines = Files.readAllLines(serverListPath);
931 }
catch (IOException ex){
932 throw new KeywordSearchModuleException(serverListName +
" could not be read", ex);
936 for (Iterator<String> iterator = lines.iterator(); iterator.hasNext();) {
937 String line = iterator.next();
938 if (! line.contains(
",")) {
943 if(lines.isEmpty()) {
944 throw new KeywordSearchModuleException(serverListName +
" had no valid server information");
948 int rnd =
new Random().nextInt(lines.size());
949 String[] parts = lines.get(rnd).split(
",");
950 if(parts.length != 2) {
951 throw new KeywordSearchModuleException(
"Invalid server data: " + lines.get(rnd));
955 String host = parts[0];
956 String port = parts[1];
957 if(host.isEmpty() || port.isEmpty()) {
958 throw new KeywordSearchModuleException(
"Invalid server data: " + lines.get(rnd));
962 Path serverFile = Paths.get(caseDirectoryPath.toString(),
"solrserver.txt");
964 caseDirectoryPath.toFile().mkdirs();
965 if (! caseDirectoryPath.toFile().exists()) {
966 throw new KeywordSearchModuleException(
"Case directory " + caseDirectoryPath.toString() +
" does not exist");
968 Files.write(serverFile, lines.get(rnd).getBytes());
969 }
catch (IOException ex){
970 throw new KeywordSearchModuleException(serverFile.toString() +
" could not be written", ex);
1009 void commit() throws SolrServerException, NoOpenCoreException {
1010 currentCoreLock.readLock().lock();
1012 if (null == currentCore) {
1013 throw new NoOpenCoreException();
1015 currentCore.commit();
1017 currentCoreLock.readLock().unlock();
1021 NamedList<Object> request(SolrRequest request)
throws SolrServerException, NoOpenCoreException {
1022 currentCoreLock.readLock().lock();
1024 if (null == currentCore) {
1025 throw new NoOpenCoreException();
1027 return currentCore.request(request);
1029 currentCoreLock.readLock().unlock();
1044 currentCoreLock.readLock().lock();
1046 if (null == currentCore) {
1047 throw new NoOpenCoreException();
1050 return currentCore.queryNumIndexedFiles();
1051 }
catch (SolrServerException | IOException ex) {
1052 throw new KeywordSearchModuleException(NbBundle.getMessage(
this.getClass(),
"Server.queryNumIdxFiles.exception.msg"), ex);
1055 currentCoreLock.readLock().unlock();
1069 currentCoreLock.readLock().lock();
1071 if (null == currentCore) {
1072 throw new NoOpenCoreException();
1075 return currentCore.queryNumIndexedChunks();
1076 }
catch (SolrServerException | IOException ex) {
1077 throw new KeywordSearchModuleException(NbBundle.getMessage(
this.getClass(),
"Server.queryNumIdxChunks.exception.msg"), ex);
1080 currentCoreLock.readLock().unlock();
1094 currentCoreLock.readLock().lock();
1096 if (null == currentCore) {
1097 throw new NoOpenCoreException();
1100 return currentCore.queryNumIndexedDocuments();
1101 }
catch (SolrServerException | IOException ex) {
1102 throw new KeywordSearchModuleException(NbBundle.getMessage(
this.getClass(),
"Server.queryNumIdxDocs.exception.msg"), ex);
1105 currentCoreLock.readLock().unlock();
1119 public boolean queryIsIndexed(
long contentID)
throws KeywordSearchModuleException, NoOpenCoreException {
1120 currentCoreLock.readLock().lock();
1122 if (null == currentCore) {
1123 throw new NoOpenCoreException();
1126 return currentCore.queryIsIndexed(contentID);
1127 }
catch (SolrServerException | IOException ex) {
1128 throw new KeywordSearchModuleException(NbBundle.getMessage(
this.getClass(),
"Server.queryIsIdxd.exception.msg"), ex);
1132 currentCoreLock.readLock().unlock();
1148 currentCoreLock.readLock().lock();
1150 if (null == currentCore) {
1151 throw new NoOpenCoreException();
1154 return currentCore.queryNumFileChunks(fileID);
1155 }
catch (SolrServerException | IOException ex) {
1156 throw new KeywordSearchModuleException(NbBundle.getMessage(
this.getClass(),
"Server.queryNumFileChunks.exception.msg"), ex);
1159 currentCoreLock.readLock().unlock();
1173 public QueryResponse
query(SolrQuery sq)
throws KeywordSearchModuleException, NoOpenCoreException, IOException {
1174 currentCoreLock.readLock().lock();
1176 if (null == currentCore) {
1177 throw new NoOpenCoreException();
1180 return currentCore.query(sq);
1181 }
catch (SolrServerException ex) {
1182 logger.log(Level.SEVERE,
"Solr query failed: " + sq.getQuery(), ex);
1183 throw new KeywordSearchModuleException(NbBundle.getMessage(
this.getClass(),
"Server.query.exception.msg", sq.getQuery()), ex);
1186 currentCoreLock.readLock().unlock();
1201 public QueryResponse
query(SolrQuery sq, SolrRequest.METHOD method) throws KeywordSearchModuleException, NoOpenCoreException {
1202 currentCoreLock.readLock().lock();
1204 if (null == currentCore) {
1205 throw new NoOpenCoreException();
1208 return currentCore.query(sq, method);
1209 }
catch (SolrServerException | IOException ex) {
1210 logger.log(Level.SEVERE,
"Solr query failed: " + sq.getQuery(), ex);
1211 throw new KeywordSearchModuleException(NbBundle.getMessage(
this.getClass(),
"Server.query2.exception.msg", sq.getQuery()), ex);
1214 currentCoreLock.readLock().unlock();
1228 public TermsResponse
queryTerms(SolrQuery sq)
throws KeywordSearchModuleException, NoOpenCoreException {
1229 currentCoreLock.readLock().lock();
1231 if (null == currentCore) {
1232 throw new NoOpenCoreException();
1235 return currentCore.queryTerms(sq);
1236 }
catch (SolrServerException | IOException ex) {
1237 logger.log(Level.SEVERE,
"Solr terms query failed: " + sq.getQuery(), ex);
1238 throw new KeywordSearchModuleException(NbBundle.getMessage(
this.getClass(),
"Server.queryTerms.exception.msg", sq.getQuery()), ex);
1241 currentCoreLock.readLock().unlock();
1255 currentCoreLock.readLock().lock();
1257 if (null == currentCore) {
1258 throw new NoOpenCoreException();
1260 return currentCore.getSolrContent(content.getId(), 0);
1262 currentCoreLock.readLock().unlock();
1278 public String
getSolrContent(
final Content content,
int chunkID)
throws NoOpenCoreException {
1279 currentCoreLock.readLock().lock();
1281 if (null == currentCore) {
1282 throw new NoOpenCoreException();
1284 return currentCore.getSolrContent(content.getId(), chunkID);
1286 currentCoreLock.readLock().unlock();
1300 currentCoreLock.readLock().lock();
1302 if (null == currentCore) {
1303 throw new NoOpenCoreException();
1305 return currentCore.getSolrContent(objectID, 0);
1307 currentCoreLock.readLock().unlock();
1321 public String
getSolrContent(
final long objectID,
final int chunkID)
throws NoOpenCoreException {
1322 currentCoreLock.readLock().lock();
1324 if (null == currentCore) {
1325 throw new NoOpenCoreException();
1327 return currentCore.getSolrContent(objectID, chunkID);
1329 currentCoreLock.readLock().unlock();
1354 void connectToSolrServer(HttpSolrServer solrServer)
throws SolrServerException, IOException {
1356 CoreAdminRequest statusRequest =
new CoreAdminRequest();
1357 statusRequest.setCoreName( null );
1358 statusRequest.setAction( CoreAdminParams.CoreAdminAction.STATUS );
1359 statusRequest.setIndexInfoNeeded(
false);
1360 statusRequest.process(solrServer);
1377 private boolean coreIsLoaded(String coreName)
throws SolrServerException, IOException {
1378 CoreAdminResponse response = CoreAdminRequest.getStatus(coreName, currentSolrServer);
1379 return response.getCoreStatus(coreName).get(
"instanceDir") != null;
1393 CoreAdminResponse response = CoreAdminRequest.getStatus(coreName, currentSolrServer);
1394 Object dataDirPath = response.getCoreStatus(coreName).get(
"dataDir");
1395 if (null != dataDirPath) {
1396 File indexDir = Paths.get((String) dataDirPath,
"index").toFile();
1397 return indexDir.exists();
1406 private final String name;
1410 private final Index textIndex;
1414 private final HttpSolrServer solrCore;
1416 private final int QUERY_TIMEOUT_MILLISECONDS = 86400000;
1418 private Core(String name,
CaseType caseType, Index index) {
1420 this.caseType = caseType;
1421 this.textIndex = index;
1423 this.solrCore =
new HttpSolrServer(currentSolrServer.getBaseURL() +
"/" + name);
1427 solrCore.setSoTimeout(QUERY_TIMEOUT_MILLISECONDS);
1429 solrCore.setDefaultMaxConnectionsPerHost(32);
1430 solrCore.setMaxTotalConnections(32);
1431 solrCore.setFollowRedirects(
false);
1434 solrCore.setAllowCompression(
true);
1435 solrCore.setParser(
new XMLResponseParser());
1448 private Index getIndexInfo() {
1449 return this.textIndex;
1452 private QueryResponse
query(SolrQuery sq)
throws SolrServerException, IOException {
1453 return solrCore.query(sq);
1456 private NamedList<Object> request(SolrRequest request)
throws SolrServerException {
1458 return solrCore.request(request);
1459 }
catch (IOException e) {
1460 logger.log(Level.WARNING,
"Could not issue Solr request. ", e);
1461 throw new SolrServerException(
1462 NbBundle.getMessage(
this.getClass(),
"Server.request.exception.exception.msg"), e);
1467 private QueryResponse
query(SolrQuery sq, SolrRequest.METHOD method) throws SolrServerException, IOException {
1468 return solrCore.query(sq, method);
1471 private TermsResponse
queryTerms(SolrQuery sq)
throws SolrServerException, IOException {
1472 QueryResponse qres = solrCore.query(sq);
1473 return qres.getTermsResponse();
1476 private void commit() throws SolrServerException {
1479 solrCore.commit(
true,
true);
1480 }
catch (IOException e) {
1481 logger.log(Level.WARNING,
"Could not commit index. ", e);
1482 throw new SolrServerException(NbBundle.getMessage(
this.getClass(),
"Server.commit.exception.msg"), e);
1486 void addDocument(SolrInputDocument doc)
throws KeywordSearchModuleException {
1489 }
catch (SolrServerException ex) {
1490 logger.log(Level.SEVERE,
"Could not add document to index via update handler: " + doc.getField(
"id"), ex);
1491 throw new KeywordSearchModuleException(
1492 NbBundle.getMessage(
this.getClass(),
"Server.addDoc.exception.msg", doc.getField(
"id")), ex);
1493 }
catch (IOException ex) {
1494 logger.log(Level.SEVERE,
"Could not add document to index via update handler: " + doc.getField(
"id"), ex);
1495 throw new KeywordSearchModuleException(
1496 NbBundle.getMessage(
this.getClass(),
"Server.addDoc.exception.msg2", doc.getField(
"id")), ex);
1510 final SolrQuery q =
new SolrQuery();
1512 String filterQuery = Schema.ID.toString() +
":" + KeywordSearchUtil.escapeLuceneQuery(Long.toString(contentID));
1514 filterQuery = filterQuery + Server.CHUNK_ID_SEPARATOR + chunkID;
1516 q.addFilterQuery(filterQuery);
1517 q.setFields(Schema.TEXT.toString());
1520 SolrDocumentList solrDocuments = solrCore.query(q).getResults();
1522 if (!solrDocuments.isEmpty()) {
1523 SolrDocument solrDocument = solrDocuments.get(0);
1524 if (solrDocument != null) {
1525 Collection<Object> fieldValues = solrDocument.getFieldValues(Schema.TEXT.toString());
1526 if (fieldValues.size() == 1)
1528 return fieldValues.toArray(
new String[0])[0];
1532 return fieldValues.toArray(
new String[0])[1];
1536 }
catch (SolrServerException ex) {
1537 logger.log(Level.SEVERE,
"Error getting content from Solr. Solr document id " + contentID +
", chunk id " + chunkID +
", query: " + filterQuery, ex);
1544 synchronized void close() throws KeywordSearchModuleException {
1551 CoreAdminRequest.unloadCore(this.name, currentSolrServer);
1552 }
catch (SolrServerException ex) {
1553 throw new KeywordSearchModuleException(
1554 NbBundle.getMessage(
this.getClass(),
"Server.close.exception.msg"), ex);
1555 }
catch (IOException ex) {
1556 throw new KeywordSearchModuleException(
1557 NbBundle.getMessage(
this.getClass(),
"Server.close.exception.msg2"), ex);
1584 SolrQuery q =
new SolrQuery(Server.Schema.ID +
":*" + Server.CHUNK_ID_SEPARATOR +
"*");
1586 int numChunks = (int)
query(q).getResults().getNumFound();
1601 SolrQuery q =
new SolrQuery(
"*:*");
1603 return (
int)
query(q).getResults().getNumFound();
1615 private boolean queryIsIndexed(
long contentID)
throws SolrServerException, IOException {
1616 String
id = KeywordSearchUtil.escapeLuceneQuery(Long.toString(contentID));
1617 SolrQuery q =
new SolrQuery(
"*:*");
1618 q.addFilterQuery(Server.Schema.ID.toString() +
":" + id);
1621 return (
int)
query(q).getResults().getNumFound() != 0;
1635 private int queryNumFileChunks(
long contentID)
throws SolrServerException, IOException {
1636 String
id = KeywordSearchUtil.escapeLuceneQuery(Long.toString(contentID));
1638 =
new SolrQuery(Server.Schema.ID +
":" +
id + Server.CHUNK_ID_SEPARATOR +
"*");
1640 return (
int)
query(q).getResults().getNumFound();
1644 class ServerAction
extends AbstractAction {
1646 private static final long serialVersionUID = 1L;
1649 public void actionPerformed(ActionEvent e) {
1650 logger.log(Level.INFO, e.paramString().trim());
1657 class SolrServerNoPortException
extends SocketException {
1659 private static final long serialVersionUID = 1L;
1664 private final int port;
1666 SolrServerNoPortException(
int port) {
1667 super(NbBundle.getMessage(Server.class,
"Server.solrServerNoPortException.msg", port,
1668 Server.PROPERTIES_CURRENT_SERVER_PORT));
1672 int getPortNumber() {
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 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 String getConfigSetting(String moduleName, String settingName)
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()
static boolean settingExists(String moduleName, String settingName)
int queryNumFileChunks(long fileID)
static final boolean DEBUG
QueryResponse query(SolrQuery sq, SolrRequest.METHOD method)