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.locks.ReentrantReadWriteLock;
46 import java.util.logging.Level;
47 import javax.swing.AbstractAction;
48 import org.apache.solr.client.solrj.SolrQuery;
49 import org.apache.solr.client.solrj.SolrRequest;
50 import org.apache.solr.client.solrj.SolrServerException;
51 import org.apache.solr.client.solrj.impl.HttpSolrServer;
52 import org.apache.solr.client.solrj.impl.XMLResponseParser;
53 import org.apache.solr.client.solrj.request.CoreAdminRequest;
54 import org.apache.solr.client.solrj.response.CoreAdminResponse;
55 import org.apache.solr.client.solrj.response.QueryResponse;
56 import org.apache.solr.client.solrj.response.TermsResponse;
57 import org.apache.solr.common.SolrDocument;
58 import org.apache.solr.common.SolrDocumentList;
59 import org.apache.solr.common.SolrException;
60 import org.apache.solr.common.SolrInputDocument;
61 import org.apache.solr.common.params.CoreAdminParams;
62 import org.apache.solr.common.util.NamedList;
63 import org.openide.modules.InstalledFileLocator;
64 import org.openide.modules.Places;
65 import org.openide.util.NbBundle;
91 public String toString() {
97 public String toString() {
104 public String toString() {
110 public String toString() {
111 return "content_str";
116 public String toString() {
122 public String toString() {
128 public String toString() {
135 public String toString() {
142 public String toString() {
149 public String toString() {
156 public String toString() {
162 public String toString() {
168 public String toString() {
186 static final String PROPERTIES_FILE = KeywordSearchSettings.MODULE_NAME;
187 static final String PROPERTIES_CURRENT_SERVER_PORT =
"IndexingServerPort";
188 static final String PROPERTIES_CURRENT_STOP_PORT =
"IndexingServerStopPort";
189 private static final String
KEY =
"jjk#09s";
190 static final String DEFAULT_SOLR_SERVER_HOST =
"localhost";
191 static final int DEFAULT_SOLR_SERVER_PORT = 23232;
192 static final int DEFAULT_SOLR_STOP_PORT = 34343;
195 private static final boolean DEBUG =
false;
196 private static final String
SOLR =
"solr";
226 this.localSolrServer =
new HttpSolrServer(
"http://localhost:" + currentSolrServerPort +
"/solr");
227 serverAction =
new ServerAction();
228 solrFolder = InstalledFileLocator.getDefault().locate(
"solr",
Server.class.getPackage().getName(),
false);
232 if (!solrHome.toFile().exists()) {
234 Files.createDirectory(solrHome);
235 Files.copy(Paths.get(solrFolder.getAbsolutePath(),
"solr",
"solr.xml"), solrHome.resolve(
"solr.xml"));
236 Files.copy(Paths.get(solrFolder.getAbsolutePath(),
"solr",
"zoo.cfg"), solrHome.resolve(
"zoo.cfg"));
237 }
catch (IOException ex) {
238 logger.log(Level.SEVERE,
"Failed to create Solr home folder:", ex);
241 currentCoreLock =
new ReentrantReadWriteLock(
true);
243 logger.log(Level.INFO,
"Created Server instance using Java at {0}", javaPath);
251 }
catch (NumberFormatException nfe) {
252 logger.log(Level.WARNING,
"Could not decode indexing server port, value was not a valid port number, using the default. ", nfe);
253 currentSolrServerPort = DEFAULT_SOLR_SERVER_PORT;
256 currentSolrServerPort = DEFAULT_SOLR_SERVER_PORT;
263 }
catch (NumberFormatException nfe) {
264 logger.log(Level.WARNING,
"Could not decode indexing server stop port, value was not a valid port number, using default", nfe);
265 currentSolrStopPort = DEFAULT_SOLR_STOP_PORT;
268 currentSolrStopPort = DEFAULT_SOLR_STOP_PORT;
274 public void finalize() throws java.lang.Throwable {
280 serverAction.addPropertyChangeListener(l);
283 int getCurrentSolrServerPort() {
287 int getCurrentSolrStopPort() {
298 volatile boolean doRun =
true;
301 this.stream = stream;
303 final String log = Places.getUserDirectory().getAbsolutePath()
304 + File.separator +
"var" + File.separator +
"log"
305 + File.separator +
"solr.log." + type;
306 File outputFile =
new File(log.concat(
".0"));
307 File first =
new File(log.concat(
".1"));
308 File second =
new File(log.concat(
".2"));
309 if (second.exists()) {
312 if (first.exists()) {
313 first.renameTo(second);
315 if (outputFile.exists()) {
316 outputFile.renameTo(first);
318 outputFile.createNewFile();
320 out =
new FileOutputStream(outputFile);
322 }
catch (Exception ex) {
323 logger.log(Level.WARNING,
"Failed to create solr log file", ex);
334 try (InputStreamReader isr =
new InputStreamReader(stream);
335 BufferedReader br =
new BufferedReader(isr);
337 BufferedWriter bw =
new BufferedWriter(osw);) {
340 while (doRun && (line = br.readLine()) != null) {
349 }
catch (IOException ex) {
350 logger.log(Level.SEVERE,
"Error redirecting Solr output stream", ex);
365 final String MAX_SOLR_MEM_MB_PAR =
"-Xmx" + Integer.toString(MAX_SOLR_MEM_MB) +
"m";
366 List<String> commandLine =
new ArrayList<>();
367 commandLine.add(javaPath);
368 commandLine.add(MAX_SOLR_MEM_MB_PAR);
369 commandLine.add(
"-DSTOP.PORT=" + currentSolrStopPort);
370 commandLine.add(
"-Djetty.port=" + currentSolrServerPort);
371 commandLine.add(
"-DSTOP.KEY=" + KEY);
372 commandLine.add(
"-jar");
373 commandLine.add(
"start.jar");
375 commandLine.addAll(solrArguments);
377 ProcessBuilder solrProcessBuilder =
new ProcessBuilder(commandLine);
378 solrProcessBuilder.directory(solrFolder);
381 Path solrStdoutPath = Paths.get(Places.getUserDirectory().getAbsolutePath(),
"var",
"log",
"solr.log.stdout");
382 solrProcessBuilder.redirectOutput(solrStdoutPath.toFile());
384 Path solrStderrPath = Paths.get(Places.getUserDirectory().getAbsolutePath(),
"var",
"log",
"solr.log.stderr");
385 solrProcessBuilder.redirectError(solrStderrPath.toFile());
387 logger.log(Level.INFO,
"Running Solr command: {0}", solrProcessBuilder.command());
388 Process process = solrProcessBuilder.start();
389 logger.log(Level.INFO,
"Finished running Solr command");
398 List<Long> getSolrPIDs() {
399 List<Long> pids =
new ArrayList<>();
402 final String pidsQuery =
"Args.*.eq=-DSTOP.KEY=" + KEY +
",Args.*.eq=start.jar";
405 if (pidsArr != null) {
406 for (
int i = 0; i < pidsArr.length; ++i) {
407 pids.add(pidsArr[i]);
419 List<Long> solrPids = getSolrPIDs();
420 for (
long pid : solrPids) {
421 logger.log(Level.INFO,
"Trying to kill old Solr process, PID: {0}", pid);
422 PlatformUtil.killProcess(pid);
431 void start() throws KeywordSearchModuleException, SolrServerNoPortException {
437 if (!isPortAvailable(currentSolrServerPort)) {
441 final List<Long> pids = this.getSolrPIDs();
445 if (pids.isEmpty()) {
446 throw new SolrServerNoPortException(currentSolrServerPort);
455 if (!isPortAvailable(currentSolrServerPort)) {
456 throw new SolrServerNoPortException(currentSolrServerPort);
458 if (!isPortAvailable(currentSolrStopPort)) {
459 throw new SolrServerNoPortException(currentSolrStopPort);
463 logger.log(Level.INFO,
"Starting Solr server from: {0}", solrFolder.getAbsolutePath());
465 if (isPortAvailable(currentSolrServerPort)) {
466 logger.log(Level.INFO,
"Port [{0}] available, starting Solr", currentSolrServerPort);
469 Arrays.asList(
"-Dbootstrap_confdir=../solr/configsets/AutopsyConfig/conf",
470 "-Dcollection.configName=AutopsyConfig")));
475 Thread.sleep(10 * 1000);
476 }
catch (InterruptedException ex) {
477 logger.log(Level.WARNING,
"Timer interrupted");
480 final List<Long> pids = this.getSolrPIDs();
481 logger.log(Level.INFO,
"New Solr process PID: {0}", pids);
482 }
catch (SecurityException ex) {
483 logger.log(Level.SEVERE,
"Could not start Solr process!", ex);
484 throw new KeywordSearchModuleException(
485 NbBundle.getMessage(
this.getClass(),
"Server.start.exception.cantStartSolr.msg"), ex);
486 }
catch (IOException ex) {
487 logger.log(Level.SEVERE,
"Could not start Solr server process!", ex);
488 throw new KeywordSearchModuleException(
489 NbBundle.getMessage(
this.getClass(),
"Server.start.exception.cantStartSolr.msg2"), ex);
499 static boolean isPortAvailable(
int port) {
500 ServerSocket ss = null;
503 ss =
new ServerSocket(port, 0, java.net.Inet4Address.getByName(
"localhost"));
505 ss.setReuseAddress(
true);
510 }
catch (IOException e) {
515 }
catch (IOException e) {
530 void changeSolrServerPort(
int port) {
531 currentSolrServerPort = port;
532 ModuleSettings.setConfigSetting(PROPERTIES_FILE, PROPERTIES_CURRENT_SERVER_PORT, String.valueOf(port));
540 void changeSolrStopPort(
int port) {
541 currentSolrStopPort = port;
542 ModuleSettings.setConfigSetting(PROPERTIES_FILE, PROPERTIES_CURRENT_STOP_PORT, String.valueOf(port));
550 synchronized void stop() {
555 }
catch (KeywordSearchModuleException e) {
556 logger.log(Level.WARNING,
"Failed to close core: ", e);
560 logger.log(Level.INFO,
"Stopping Solr server from: {0}", solrFolder.getAbsolutePath());
563 Process process =
runSolrCommand(
new ArrayList<>(Arrays.asList(
"--stop")));
565 logger.log(Level.INFO,
"Waiting for Solr server to stop");
569 if (curSolrProcess != null) {
570 curSolrProcess.destroy();
571 curSolrProcess = null;
574 }
catch (IOException | InterruptedException ex) {
575 logger.log(Level.WARNING,
"Error while attempting to stop Solr server", ex);
579 if (errorRedirectThread != null) {
580 errorRedirectThread.stopRun();
581 errorRedirectThread = null;
588 logger.log(Level.INFO,
"Finished stopping Solr server");
599 synchronized boolean isRunning() throws KeywordSearchModuleException {
602 if (isPortAvailable(currentSolrServerPort)) {
609 connectToSolrServer(localSolrServer);
611 logger.log(Level.INFO,
"Solr server is running");
612 }
catch (SolrServerException ex) {
614 Throwable cause = ex.getRootCause();
619 if (cause instanceof ConnectException || cause instanceof SocketException) {
620 logger.log(Level.INFO,
"Solr server is not running, cause: {0}", cause.getMessage());
623 throw new KeywordSearchModuleException(
624 NbBundle.getMessage(
this.getClass(),
"Server.isRunning.exception.errCheckSolrRunning.msg"), ex);
626 }
catch (SolrException ex) {
628 logger.log(Level.INFO,
"Solr server is not running", ex);
630 }
catch (IOException ex) {
631 throw new KeywordSearchModuleException(
632 NbBundle.getMessage(
this.getClass(),
"Server.isRunning.exception.errCheckSolrRunning.msg2"), ex);
650 void openCoreForCase(Case theCase, Index index)
throws KeywordSearchModuleException {
651 currentCoreLock.writeLock().lock();
653 currentCore =
openCore(theCase, index);
658 }
catch (NoOpenCoreException ex) {
659 throw new KeywordSearchModuleException(NbBundle.getMessage(
this.getClass(),
"Server.openCore.exception.cantOpen.msg"), ex);
662 serverAction.putValue(CORE_EVT, CORE_EVT_STATES.STARTED);
664 currentCoreLock.writeLock().unlock();
673 boolean coreIsOpen() {
674 currentCoreLock.readLock().lock();
676 return (null != currentCore);
678 currentCoreLock.readLock().unlock();
682 Index getIndexInfo() throws NoOpenCoreException {
683 currentCoreLock.readLock().lock();
685 if (null == currentCore) {
686 throw new NoOpenCoreException();
688 return currentCore.getIndexInfo();
690 currentCoreLock.readLock().unlock();
694 void closeCore() throws KeywordSearchModuleException {
695 currentCoreLock.writeLock().lock();
697 if (null != currentCore) {
700 serverAction.putValue(CORE_EVT, CORE_EVT_STATES.STOPPED);
703 currentCoreLock.writeLock().unlock();
707 void addDocument(SolrInputDocument doc)
throws KeywordSearchModuleException, NoOpenCoreException {
708 currentCoreLock.readLock().lock();
710 if (null == currentCore) {
711 throw new NoOpenCoreException();
713 TimingMetric metric = HealthMonitor.getTimingMetric(
"Solr: Index chunk");
714 currentCore.addDocument(doc);
715 HealthMonitor.submitTimingMetric(metric);
717 currentCoreLock.readLock().unlock();
730 "# {0} - core name",
"Server.deleteCore.exception.msg=Failed to delete Solr core {0}",})
731 void deleteCore(String coreName, CaseMetadata metadata)
throws KeywordSearchServiceException {
733 HttpSolrServer solrServer;
734 if (metadata.getCaseType() == CaseType.SINGLE_USER_CASE) {
735 Integer localSolrServerPort = Integer.decode(ModuleSettings.getConfigSetting(PROPERTIES_FILE, PROPERTIES_CURRENT_SERVER_PORT));
736 solrServer =
new HttpSolrServer(
"http://localhost:" + localSolrServerPort +
"/solr");
739 solrServer =
new HttpSolrServer(
"http://" + properties.getHost() +
":" + properties.getPort() +
"/solr");
741 connectToSolrServer(solrServer);
742 CoreAdminResponse response = CoreAdminRequest.getStatus(coreName, solrServer);
743 if (null != response.getCoreStatus(coreName).get(
"instanceDir")) {
753 org.apache.solr.client.solrj.request.CoreAdminRequest.unloadCore(coreName,
true,
true, solrServer);
755 }
catch (SolrServerException | HttpSolrServer.RemoteSolrException | IOException ex) {
758 if (!ex.getMessage().equals(
"Already closed")) {
759 throw new KeywordSearchServiceException(Bundle.Server_deleteCore_exception_msg(coreName), ex);
775 private Core
openCore(
Case theCase, Index index)
throws KeywordSearchModuleException {
782 currentSolrServer =
new HttpSolrServer(
"http://" + properties.
getHost() +
":" + properties.
getPort() +
"/solr");
785 connectToSolrServer(currentSolrServer);
788 }
catch (SolrServerException | IOException ex) {
789 throw new KeywordSearchModuleException(NbBundle.getMessage(
Server.class,
"Server.connect.exception.msg", ex.getLocalizedMessage()), ex);
793 File dataDir =
new File(
new File(index.getIndexPath()).getParent());
794 if (!dataDir.exists()) {
798 if (!this.isRunning()) {
799 logger.log(Level.SEVERE,
"Core create/open requested, but server not yet running");
800 throw new KeywordSearchModuleException(NbBundle.getMessage(
this.getClass(),
"Server.openCore.exception.msg"));
803 String coreName = index.getIndexName();
814 Path corePropertiesFile = Paths.get(solrFolder.toString(),
SOLR, coreName,
CORE_PROPERTIES);
815 if (corePropertiesFile.toFile().exists()) {
817 corePropertiesFile.toFile().delete();
818 }
catch (Exception ex) {
819 logger.log(Level.INFO,
"Could not delete pre-existing core.properties prior to opening the core.");
824 CoreAdminRequest.Create createCoreRequest =
new CoreAdminRequest.Create();
825 createCoreRequest.setDataDir(dataDir.getAbsolutePath());
826 createCoreRequest.setCoreName(coreName);
827 createCoreRequest.setConfigSet(
"AutopsyConfig");
828 createCoreRequest.setIsLoadOnStartup(
false);
829 createCoreRequest.setIsTransient(
true);
830 currentSolrServer.request(createCoreRequest);
834 throw new KeywordSearchModuleException(NbBundle.getMessage(
this.getClass(),
"Server.openCore.exception.noIndexDir.msg"));
837 return new Core(coreName, theCase.getCaseType(), index);
839 }
catch (Exception ex) {
840 throw new KeywordSearchModuleException(NbBundle.getMessage(
this.getClass(),
"Server.openCore.exception.cantOpen.msg"), ex);
854 Path serverFilePath = Paths.get(caseDirectory,
"solrserver.txt");
855 if(serverFilePath.toFile().exists()){
857 List<String> lines = Files.readAllLines(serverFilePath);
858 if(lines.isEmpty()) {
859 logger.log(Level.SEVERE,
"solrserver.txt file does not contain any data");
860 }
else if (! lines.get(0).contains(
",")) {
861 logger.log(Level.SEVERE,
"solrserver.txt file is corrupt - could not read host/port from " + lines.get(0));
863 String[] parts = lines.get(0).split(
",");
864 if(parts.length != 2) {
865 logger.log(Level.SEVERE,
"solrserver.txt file is corrupt - could not read host/port from " + lines.get(0));
870 }
catch (IOException ex) {
871 logger.log(Level.SEVERE,
"solrserver.txt file could not be read", ex);
894 public static void selectSolrServerForCase(Path rootOutputDirectory, Path caseDirectoryPath)
throws KeywordSearchModuleException {
896 String serverListName =
"solrServerList.txt";
897 Path serverListPath = Paths.get(rootOutputDirectory.toString(), serverListName);
898 if(serverListPath.toFile().exists()){
903 lines = Files.readAllLines(serverListPath);
904 }
catch (IOException ex){
905 throw new KeywordSearchModuleException(serverListName +
" could not be read", ex);
909 for (Iterator<String> iterator = lines.iterator(); iterator.hasNext();) {
910 String line = iterator.next();
911 if (! line.contains(
",")) {
916 if(lines.isEmpty()) {
917 throw new KeywordSearchModuleException(serverListName +
" had no valid server information");
921 int rnd =
new Random().nextInt(lines.size());
922 String[] parts = lines.get(rnd).split(
",");
923 if(parts.length != 2) {
924 throw new KeywordSearchModuleException(
"Invalid server data: " + lines.get(rnd));
928 String host = parts[0];
929 String port = parts[1];
930 if(host.isEmpty() || port.isEmpty()) {
931 throw new KeywordSearchModuleException(
"Invalid server data: " + lines.get(rnd));
935 Path serverFile = Paths.get(caseDirectoryPath.toString(),
"solrserver.txt");
937 caseDirectoryPath.toFile().mkdirs();
938 if (! caseDirectoryPath.toFile().exists()) {
939 throw new KeywordSearchModuleException(
"Case directory " + caseDirectoryPath.toString() +
" does not exist");
941 Files.write(serverFile, lines.get(rnd).getBytes());
942 }
catch (IOException ex){
943 throw new KeywordSearchModuleException(serverFile.toString() +
" could not be written", ex);
982 void commit() throws SolrServerException, NoOpenCoreException {
983 currentCoreLock.readLock().lock();
985 if (null == currentCore) {
986 throw new NoOpenCoreException();
988 currentCore.commit();
990 currentCoreLock.readLock().unlock();
994 NamedList<Object> request(SolrRequest request)
throws SolrServerException, NoOpenCoreException {
995 currentCoreLock.readLock().lock();
997 if (null == currentCore) {
998 throw new NoOpenCoreException();
1000 return currentCore.request(request);
1002 currentCoreLock.readLock().unlock();
1017 currentCoreLock.readLock().lock();
1019 if (null == currentCore) {
1020 throw new NoOpenCoreException();
1023 return currentCore.queryNumIndexedFiles();
1024 }
catch (SolrServerException | IOException ex) {
1025 throw new KeywordSearchModuleException(NbBundle.getMessage(
this.getClass(),
"Server.queryNumIdxFiles.exception.msg"), ex);
1028 currentCoreLock.readLock().unlock();
1042 currentCoreLock.readLock().lock();
1044 if (null == currentCore) {
1045 throw new NoOpenCoreException();
1048 return currentCore.queryNumIndexedChunks();
1049 }
catch (SolrServerException | IOException ex) {
1050 throw new KeywordSearchModuleException(NbBundle.getMessage(
this.getClass(),
"Server.queryNumIdxChunks.exception.msg"), ex);
1053 currentCoreLock.readLock().unlock();
1067 currentCoreLock.readLock().lock();
1069 if (null == currentCore) {
1070 throw new NoOpenCoreException();
1073 return currentCore.queryNumIndexedDocuments();
1074 }
catch (SolrServerException | IOException ex) {
1075 throw new KeywordSearchModuleException(NbBundle.getMessage(
this.getClass(),
"Server.queryNumIdxDocs.exception.msg"), ex);
1078 currentCoreLock.readLock().unlock();
1092 public boolean queryIsIndexed(
long contentID)
throws KeywordSearchModuleException, NoOpenCoreException {
1093 currentCoreLock.readLock().lock();
1095 if (null == currentCore) {
1096 throw new NoOpenCoreException();
1099 return currentCore.queryIsIndexed(contentID);
1100 }
catch (SolrServerException | IOException ex) {
1101 throw new KeywordSearchModuleException(NbBundle.getMessage(
this.getClass(),
"Server.queryIsIdxd.exception.msg"), ex);
1105 currentCoreLock.readLock().unlock();
1121 currentCoreLock.readLock().lock();
1123 if (null == currentCore) {
1124 throw new NoOpenCoreException();
1127 return currentCore.queryNumFileChunks(fileID);
1128 }
catch (SolrServerException | IOException ex) {
1129 throw new KeywordSearchModuleException(NbBundle.getMessage(
this.getClass(),
"Server.queryNumFileChunks.exception.msg"), ex);
1132 currentCoreLock.readLock().unlock();
1146 public QueryResponse
query(SolrQuery sq)
throws KeywordSearchModuleException, NoOpenCoreException, IOException {
1147 currentCoreLock.readLock().lock();
1149 if (null == currentCore) {
1150 throw new NoOpenCoreException();
1153 return currentCore.query(sq);
1154 }
catch (SolrServerException ex) {
1155 logger.log(Level.SEVERE,
"Solr query failed: " + sq.getQuery(), ex);
1156 throw new KeywordSearchModuleException(NbBundle.getMessage(
this.getClass(),
"Server.query.exception.msg", sq.getQuery()), ex);
1159 currentCoreLock.readLock().unlock();
1174 public QueryResponse
query(SolrQuery sq, SolrRequest.METHOD method) throws KeywordSearchModuleException, NoOpenCoreException {
1175 currentCoreLock.readLock().lock();
1177 if (null == currentCore) {
1178 throw new NoOpenCoreException();
1181 return currentCore.query(sq, method);
1182 }
catch (SolrServerException | IOException ex) {
1183 logger.log(Level.SEVERE,
"Solr query failed: " + sq.getQuery(), ex);
1184 throw new KeywordSearchModuleException(NbBundle.getMessage(
this.getClass(),
"Server.query2.exception.msg", sq.getQuery()), ex);
1187 currentCoreLock.readLock().unlock();
1201 public TermsResponse
queryTerms(SolrQuery sq)
throws KeywordSearchModuleException, NoOpenCoreException {
1202 currentCoreLock.readLock().lock();
1204 if (null == currentCore) {
1205 throw new NoOpenCoreException();
1208 return currentCore.queryTerms(sq);
1209 }
catch (SolrServerException | IOException ex) {
1210 logger.log(Level.SEVERE,
"Solr terms query failed: " + sq.getQuery(), ex);
1211 throw new KeywordSearchModuleException(NbBundle.getMessage(
this.getClass(),
"Server.queryTerms.exception.msg", sq.getQuery()), ex);
1214 currentCoreLock.readLock().unlock();
1228 currentCoreLock.readLock().lock();
1230 if (null == currentCore) {
1231 throw new NoOpenCoreException();
1233 return currentCore.getSolrContent(content.getId(), 0);
1235 currentCoreLock.readLock().unlock();
1251 public String
getSolrContent(
final Content content,
int chunkID)
throws NoOpenCoreException {
1252 currentCoreLock.readLock().lock();
1254 if (null == currentCore) {
1255 throw new NoOpenCoreException();
1257 return currentCore.getSolrContent(content.getId(), chunkID);
1259 currentCoreLock.readLock().unlock();
1273 currentCoreLock.readLock().lock();
1275 if (null == currentCore) {
1276 throw new NoOpenCoreException();
1278 return currentCore.getSolrContent(objectID, 0);
1280 currentCoreLock.readLock().unlock();
1294 public String
getSolrContent(
final long objectID,
final int chunkID)
throws NoOpenCoreException {
1295 currentCoreLock.readLock().lock();
1297 if (null == currentCore) {
1298 throw new NoOpenCoreException();
1300 return currentCore.getSolrContent(objectID, chunkID);
1302 currentCoreLock.readLock().unlock();
1327 void connectToSolrServer(HttpSolrServer solrServer)
throws SolrServerException, IOException {
1329 CoreAdminRequest statusRequest =
new CoreAdminRequest();
1330 statusRequest.setCoreName( null );
1331 statusRequest.setAction( CoreAdminParams.CoreAdminAction.STATUS );
1332 statusRequest.setIndexInfoNeeded(
false);
1333 statusRequest.process(solrServer);
1350 private boolean coreIsLoaded(String coreName)
throws SolrServerException, IOException {
1351 CoreAdminResponse response = CoreAdminRequest.getStatus(coreName, currentSolrServer);
1352 return response.getCoreStatus(coreName).get(
"instanceDir") != null;
1366 CoreAdminResponse response = CoreAdminRequest.getStatus(coreName, currentSolrServer);
1367 Object dataDirPath = response.getCoreStatus(coreName).get(
"dataDir");
1368 if (null != dataDirPath) {
1369 File indexDir = Paths.get((String) dataDirPath,
"index").toFile();
1370 return indexDir.exists();
1379 private final String name;
1383 private final Index textIndex;
1387 private final HttpSolrServer solrCore;
1389 private final int QUERY_TIMEOUT_MILLISECONDS = 86400000;
1391 private Core(String name,
CaseType caseType, Index index) {
1393 this.caseType = caseType;
1394 this.textIndex = index;
1396 this.solrCore =
new HttpSolrServer(currentSolrServer.getBaseURL() +
"/" + name);
1400 solrCore.setSoTimeout(QUERY_TIMEOUT_MILLISECONDS);
1402 solrCore.setDefaultMaxConnectionsPerHost(32);
1403 solrCore.setMaxTotalConnections(32);
1404 solrCore.setFollowRedirects(
false);
1407 solrCore.setAllowCompression(
true);
1408 solrCore.setParser(
new XMLResponseParser());
1421 private Index getIndexInfo() {
1422 return this.textIndex;
1425 private QueryResponse
query(SolrQuery sq)
throws SolrServerException, IOException {
1426 return solrCore.query(sq);
1429 private NamedList<Object> request(SolrRequest request)
throws SolrServerException {
1431 return solrCore.request(request);
1432 }
catch (IOException e) {
1433 logger.log(Level.WARNING,
"Could not issue Solr request. ", e);
1434 throw new SolrServerException(
1435 NbBundle.getMessage(
this.getClass(),
"Server.request.exception.exception.msg"), e);
1440 private QueryResponse
query(SolrQuery sq, SolrRequest.METHOD method) throws SolrServerException, IOException {
1441 return solrCore.query(sq, method);
1444 private TermsResponse
queryTerms(SolrQuery sq)
throws SolrServerException, IOException {
1445 QueryResponse qres = solrCore.query(sq);
1446 return qres.getTermsResponse();
1449 private void commit() throws SolrServerException {
1452 solrCore.commit(
true,
true);
1453 }
catch (IOException e) {
1454 logger.log(Level.WARNING,
"Could not commit index. ", e);
1455 throw new SolrServerException(NbBundle.getMessage(
this.getClass(),
"Server.commit.exception.msg"), e);
1459 void addDocument(SolrInputDocument doc)
throws KeywordSearchModuleException {
1462 }
catch (SolrServerException ex) {
1463 logger.log(Level.SEVERE,
"Could not add document to index via update handler: " + doc.getField(
"id"), ex);
1464 throw new KeywordSearchModuleException(
1465 NbBundle.getMessage(
this.getClass(),
"Server.addDoc.exception.msg", doc.getField(
"id")), ex);
1466 }
catch (IOException ex) {
1467 logger.log(Level.SEVERE,
"Could not add document to index via update handler: " + doc.getField(
"id"), ex);
1468 throw new KeywordSearchModuleException(
1469 NbBundle.getMessage(
this.getClass(),
"Server.addDoc.exception.msg2", doc.getField(
"id")), ex);
1483 final SolrQuery q =
new SolrQuery();
1485 String filterQuery = Schema.ID.toString() +
":" + KeywordSearchUtil.escapeLuceneQuery(Long.toString(contentID));
1487 filterQuery = filterQuery + Server.CHUNK_ID_SEPARATOR + chunkID;
1489 q.addFilterQuery(filterQuery);
1490 q.setFields(Schema.TEXT.toString());
1493 SolrDocumentList solrDocuments = solrCore.query(q).getResults();
1495 if (!solrDocuments.isEmpty()) {
1496 SolrDocument solrDocument = solrDocuments.get(0);
1497 if (solrDocument != null) {
1498 Collection<Object> fieldValues = solrDocument.getFieldValues(Schema.TEXT.toString());
1499 if (fieldValues.size() == 1)
1501 return fieldValues.toArray(
new String[0])[0];
1505 return fieldValues.toArray(
new String[0])[1];
1509 }
catch (SolrServerException ex) {
1510 logger.log(Level.SEVERE,
"Error getting content from Solr. Solr document id " + contentID +
", chunk id " + chunkID +
", query: " + filterQuery, ex);
1517 synchronized void close() throws KeywordSearchModuleException {
1524 CoreAdminRequest.unloadCore(this.name, currentSolrServer);
1525 }
catch (SolrServerException ex) {
1526 throw new KeywordSearchModuleException(
1527 NbBundle.getMessage(
this.getClass(),
"Server.close.exception.msg"), ex);
1528 }
catch (IOException ex) {
1529 throw new KeywordSearchModuleException(
1530 NbBundle.getMessage(
this.getClass(),
"Server.close.exception.msg2"), ex);
1557 SolrQuery q =
new SolrQuery(Server.Schema.ID +
":*" + Server.CHUNK_ID_SEPARATOR +
"*");
1559 int numChunks = (int)
query(q).getResults().getNumFound();
1574 SolrQuery q =
new SolrQuery(
"*:*");
1576 return (
int)
query(q).getResults().getNumFound();
1588 private boolean queryIsIndexed(
long contentID)
throws SolrServerException, IOException {
1589 String
id = KeywordSearchUtil.escapeLuceneQuery(Long.toString(contentID));
1590 SolrQuery q =
new SolrQuery(
"*:*");
1591 q.addFilterQuery(Server.Schema.ID.toString() +
":" + id);
1594 return (
int)
query(q).getResults().getNumFound() != 0;
1608 private int queryNumFileChunks(
long contentID)
throws SolrServerException, IOException {
1609 String
id = KeywordSearchUtil.escapeLuceneQuery(Long.toString(contentID));
1611 =
new SolrQuery(Server.Schema.ID +
":" +
id + Server.CHUNK_ID_SEPARATOR +
"*");
1613 return (
int)
query(q).getResults().getNumFound();
1617 class ServerAction
extends AbstractAction {
1619 private static final long serialVersionUID = 1L;
1622 public void actionPerformed(ActionEvent e) {
1623 logger.log(Level.INFO, e.paramString().trim());
1630 class SolrServerNoPortException
extends SocketException {
1632 private static final long serialVersionUID = 1L;
1637 private final int port;
1639 SolrServerNoPortException(
int port) {
1640 super(NbBundle.getMessage(Server.class,
"Server.solrServerNoPortException.msg", port,
1641 Server.PROPERTIES_CURRENT_SERVER_PORT));
1645 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 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 final int MAX_SOLR_MEM_MB
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)