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)