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() {
 
  185     static final String PROPERTIES_FILE = KeywordSearchSettings.MODULE_NAME;
 
  186     static final String PROPERTIES_CURRENT_SERVER_PORT = 
"IndexingServerPort"; 
 
  187     static final String PROPERTIES_CURRENT_STOP_PORT = 
"IndexingServerStopPort"; 
 
  188     private static final String 
KEY = 
"jjk#09s"; 
 
  189     static final String DEFAULT_SOLR_SERVER_HOST = 
"localhost"; 
 
  190     static final int DEFAULT_SOLR_SERVER_PORT = 23232;
 
  191     static final int DEFAULT_SOLR_STOP_PORT = 34343;
 
  194     private static final boolean DEBUG = 
false;
 
  195     private static final String 
SOLR = 
"solr";
 
  225         this.localSolrServer = 
new HttpSolrServer(
"http://localhost:" + currentSolrServerPort + 
"/solr"); 
 
  226         serverAction = 
new ServerAction();
 
  227         solrFolder = InstalledFileLocator.getDefault().locate(
"solr", 
Server.class.getPackage().getName(), 
false); 
 
  231         if (!solrHome.toFile().exists()) {
 
  233                 Files.createDirectory(solrHome);
 
  234                 Files.copy(Paths.get(solrFolder.getAbsolutePath(), 
"solr", 
"solr.xml"), solrHome.resolve(
"solr.xml")); 
 
  235                 Files.copy(Paths.get(solrFolder.getAbsolutePath(), 
"solr", 
"zoo.cfg"), solrHome.resolve(
"zoo.cfg")); 
 
  236             } 
catch (IOException ex) {
 
  237                 logger.log(Level.SEVERE, 
"Failed to create Solr home folder:", ex); 
 
  240         currentCoreLock = 
new ReentrantReadWriteLock(
true);
 
  242         logger.log(Level.INFO, 
"Created Server instance using Java at {0}", javaPath); 
 
  250             } 
catch (NumberFormatException nfe) {
 
  251                 logger.log(Level.WARNING, 
"Could not decode indexing server port, value was not a valid port number, using the default. ", nfe); 
 
  252                 currentSolrServerPort = DEFAULT_SOLR_SERVER_PORT;
 
  255             currentSolrServerPort = DEFAULT_SOLR_SERVER_PORT;
 
  262             } 
catch (NumberFormatException nfe) {
 
  263                 logger.log(Level.WARNING, 
"Could not decode indexing server stop port, value was not a valid port number, using default", nfe); 
 
  264                 currentSolrStopPort = DEFAULT_SOLR_STOP_PORT;
 
  267             currentSolrStopPort = DEFAULT_SOLR_STOP_PORT;
 
  273     public void finalize() throws java.lang.Throwable {
 
  279         serverAction.addPropertyChangeListener(l);
 
  282     int getCurrentSolrServerPort() {
 
  286     int getCurrentSolrStopPort() {
 
  297         volatile boolean doRun = 
true;
 
  300             this.stream = stream;
 
  302                 final String log = Places.getUserDirectory().getAbsolutePath()
 
  303                         + File.separator + 
"var" + File.separator + 
"log"  
  304                         + File.separator + 
"solr.log." + type; 
 
  305                 File outputFile = 
new File(log.concat(
".0"));
 
  306                 File first = 
new File(log.concat(
".1"));
 
  307                 File second = 
new File(log.concat(
".2"));
 
  308                 if (second.exists()) {
 
  311                 if (first.exists()) {
 
  312                     first.renameTo(second);
 
  314                 if (outputFile.exists()) {
 
  315                     outputFile.renameTo(first);
 
  317                     outputFile.createNewFile();
 
  319                 out = 
new FileOutputStream(outputFile);
 
  321             } 
catch (Exception ex) {
 
  322                 logger.log(Level.WARNING, 
"Failed to create solr log file", ex); 
 
  333             try (InputStreamReader isr = 
new InputStreamReader(stream);
 
  334                     BufferedReader br = 
new BufferedReader(isr);
 
  336                     BufferedWriter bw = 
new BufferedWriter(osw);) {
 
  339                 while (doRun && (line = br.readLine()) != null) {
 
  348             } 
catch (IOException ex) {
 
  349                 logger.log(Level.SEVERE, 
"Error redirecting Solr output stream", ex); 
 
  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 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)