Autopsy  4.12.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
Server.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2011-2019 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.autopsy.keywordsearch;
20 
21 import java.awt.event.ActionEvent;
22 import java.beans.PropertyChangeListener;
23 import java.io.BufferedReader;
24 import java.io.BufferedWriter;
25 import java.io.File;
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;
79 import org.sleuthkit.datamodel.Content;
80 
85 public class Server {
86 
90  public static enum Schema {
91 
92  ID {
93  @Override
94  public String toString() {
95  return "id"; //NON-NLS
96  }
97  },
98  IMAGE_ID {
99  @Override
100  public String toString() {
101  return "image_id"; //NON-NLS
102  }
103  },
104  // This is not stored or indexed. it is copied to text by the schema
105  CONTENT {
106  @Override
107  public String toString() {
108  return "content"; //NON-NLS
109  }
110  },
111  // String representation for regular expression searching
112  CONTENT_STR {
113  @Override
114  public String toString() {
115  return "content_str"; //NON-NLS
116  }
117  },
118  // default search field. Populated by schema
119  TEXT {
120  @Override
121  public String toString() {
122  return "text"; //NON-NLS
123  }
124  },
125  // no longer populated. Was used for regular expression searching.
126  // Should not be used.
127  CONTENT_WS {
128  @Override
129  public String toString() {
130  return "content_ws"; //NON-NLS
131  }
132  },
133  FILE_NAME {
134  @Override
135  public String toString() {
136  return "file_name"; //NON-NLS
137  }
138  },
139  // note that we no longer store or index this field
140  CTIME {
141  @Override
142  public String toString() {
143  return "ctime"; //NON-NLS
144  }
145  },
146  // note that we no longer store or index this field
147  ATIME {
148  @Override
149  public String toString() {
150  return "atime"; //NON-NLS
151  }
152  },
153  // note that we no longer store or index this field
154  MTIME {
155  @Override
156  public String toString() {
157  return "mtime"; //NON-NLS
158  }
159  },
160  // note that we no longer store or index this field
161  CRTIME {
162  @Override
163  public String toString() {
164  return "crtime"; //NON-NLS
165  }
166  },
167  NUM_CHUNKS {
168  @Override
169  public String toString() {
170  return "num_chunks"; //NON-NLS
171  }
172  },
173  CHUNK_SIZE {
174  @Override
175  public String toString() {
176  return "chunk_size"; //NON-NLS
177  }
178  }
179  };
180 
181  public static final String HL_ANALYZE_CHARS_UNLIMITED = "500000"; //max 1MB in a chunk. use -1 for unlimited, but -1 option may not be supported (not documented)
182  //max content size we can send to Solr
183  public static final long MAX_CONTENT_SIZE = 1L * 31 * 1024 * 1024;
184  private static final Logger logger = Logger.getLogger(Server.class.getName());
185  public static final String CORE_EVT = "CORE_EVT"; //NON-NLS
186  @Deprecated
187  public static final char ID_CHUNK_SEP = '_';
188  public static final String CHUNK_ID_SEPARATOR = "_";
189  private String javaPath = "java";
190  public static final Charset DEFAULT_INDEXED_TEXT_CHARSET = Charset.forName("UTF-8");
191  private Process curSolrProcess = null;
192  static final String PROPERTIES_FILE = KeywordSearchSettings.MODULE_NAME;
193  static final String PROPERTIES_CURRENT_SERVER_PORT = "IndexingServerPort"; //NON-NLS
194  static final String PROPERTIES_CURRENT_STOP_PORT = "IndexingServerStopPort"; //NON-NLS
195  private static final String KEY = "jjk#09s"; //NON-NLS
196  static final String DEFAULT_SOLR_SERVER_HOST = "localhost"; //NON-NLS
197  static final int DEFAULT_SOLR_SERVER_PORT = 23232;
198  static final int DEFAULT_SOLR_STOP_PORT = 34343;
199  private int currentSolrServerPort = 0;
200  private int currentSolrStopPort = 0;
201  private static final boolean DEBUG = false;//(Version.getBuildType() == Version.Type.DEVELOPMENT);
202  private static final String SOLR = "solr";
203  private static final String CORE_PROPERTIES = "core.properties";
204 
205  public enum CORE_EVT_STATES {
206 
207  STOPPED, STARTED
208  };
209 
210  // A reference to the locally running Solr instance.
211  private final HttpSolrServer localSolrServer;
212 
213  // A reference to the Solr server we are currently connected to for the Case.
214  // This could be a local or remote server.
215  private HttpSolrServer currentSolrServer;
216 
217  private Core currentCore;
218  private final ReentrantReadWriteLock currentCoreLock;
219 
220  private final File solrFolder;
221  private Path solrHome;
222  private final ServerAction serverAction;
224 
229  Server() {
230  initSettings();
231 
232  this.localSolrServer = new HttpSolrServer("http://localhost:" + currentSolrServerPort + "/solr"); //NON-NLS
233  serverAction = new ServerAction();
234  solrFolder = InstalledFileLocator.getDefault().locate("solr", Server.class.getPackage().getName(), false); //NON-NLS
235  javaPath = PlatformUtil.getJavaPath();
236 
237  solrHome = Paths.get(PlatformUtil.getUserDirectory().getAbsolutePath(), "solr"); //NON-NLS
238  if (!solrHome.toFile().exists()) {
239  try {
240  Files.createDirectory(solrHome);
241  Files.copy(Paths.get(solrFolder.getAbsolutePath(), "solr", "solr.xml"), solrHome.resolve("solr.xml")); //NON-NLS
242  Files.copy(Paths.get(solrFolder.getAbsolutePath(), "solr", "zoo.cfg"), solrHome.resolve("zoo.cfg")); //NON-NLS
243  } catch (IOException ex) {
244  logger.log(Level.SEVERE, "Failed to create Solr home folder:", ex); //NON-NLS
245  }
246  }
247  currentCoreLock = new ReentrantReadWriteLock(true);
248 
249  logger.log(Level.INFO, "Created Server instance using Java at {0}", javaPath); //NON-NLS
250  }
251 
252  private void initSettings() {
253 
254  if (ModuleSettings.settingExists(PROPERTIES_FILE, PROPERTIES_CURRENT_SERVER_PORT)) {
255  try {
256  currentSolrServerPort = Integer.decode(ModuleSettings.getConfigSetting(PROPERTIES_FILE, PROPERTIES_CURRENT_SERVER_PORT));
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); //NON-NLS
259  currentSolrServerPort = DEFAULT_SOLR_SERVER_PORT;
260  }
261  } else {
262  currentSolrServerPort = DEFAULT_SOLR_SERVER_PORT;
263  ModuleSettings.setConfigSetting(PROPERTIES_FILE, PROPERTIES_CURRENT_SERVER_PORT, String.valueOf(currentSolrServerPort));
264  }
265 
266  if (ModuleSettings.settingExists(PROPERTIES_FILE, PROPERTIES_CURRENT_STOP_PORT)) {
267  try {
268  currentSolrStopPort = Integer.decode(ModuleSettings.getConfigSetting(PROPERTIES_FILE, PROPERTIES_CURRENT_STOP_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); //NON-NLS
271  currentSolrStopPort = DEFAULT_SOLR_STOP_PORT;
272  }
273  } else {
274  currentSolrStopPort = DEFAULT_SOLR_STOP_PORT;
275  ModuleSettings.setConfigSetting(PROPERTIES_FILE, PROPERTIES_CURRENT_STOP_PORT, String.valueOf(currentSolrStopPort));
276  }
277  }
278 
279  @Override
280  public void finalize() throws java.lang.Throwable {
281  stop();
282  super.finalize();
283  }
284 
285  public void addServerActionListener(PropertyChangeListener l) {
286  serverAction.addPropertyChangeListener(l);
287  }
288 
289  int getCurrentSolrServerPort() {
290  return currentSolrServerPort;
291  }
292 
293  int getCurrentSolrStopPort() {
294  return currentSolrStopPort;
295  }
296 
300  private static class InputStreamPrinterThread extends Thread {
301 
302  InputStream stream;
303  OutputStream out;
304  volatile boolean doRun = true;
305 
306  InputStreamPrinterThread(InputStream stream, String type) {
307  this.stream = stream;
308  try {
309  final String log = Places.getUserDirectory().getAbsolutePath()
310  + File.separator + "var" + File.separator + "log" //NON-NLS
311  + File.separator + "solr.log." + type; //NON-NLS
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()) {
316  second.delete();
317  }
318  if (first.exists()) {
319  first.renameTo(second);
320  }
321  if (outputFile.exists()) {
322  outputFile.renameTo(first);
323  } else {
324  outputFile.createNewFile();
325  }
326  out = new FileOutputStream(outputFile);
327 
328  } catch (Exception ex) {
329  logger.log(Level.WARNING, "Failed to create solr log file", ex); //NON-NLS
330  }
331  }
332 
333  void stopRun() {
334  doRun = false;
335  }
336 
337  @Override
338  public void run() {
339 
340  try (InputStreamReader isr = new InputStreamReader(stream);
341  BufferedReader br = new BufferedReader(isr);
342  OutputStreamWriter osw = new OutputStreamWriter(out, PlatformUtil.getDefaultPlatformCharset());
343  BufferedWriter bw = new BufferedWriter(osw);) {
344 
345  String line = null;
346  while (doRun && (line = br.readLine()) != null) {
347  bw.write(line);
348  bw.newLine();
349  if (DEBUG) {
350  //flush buffers if dev version for debugging
351  bw.flush();
352  }
353  }
354  bw.flush();
355  } catch (IOException ex) {
356  logger.log(Level.SEVERE, "Error redirecting Solr output stream", ex); //NON-NLS
357  }
358  }
359  }
360 
370  private Process runSolrCommand(List<String> solrArguments) throws IOException {
371  final String MAX_SOLR_MEM_MB_PAR = "-Xmx" + UserPreferences.getMaxSolrVMSize() + "m"; //NON-NLS
372 
373  List<String> commandLine = new ArrayList<>();
374  commandLine.add(javaPath);
375  commandLine.add(MAX_SOLR_MEM_MB_PAR);
376  commandLine.add("-DSTOP.PORT=" + currentSolrStopPort); //NON-NLS
377  commandLine.add("-Djetty.port=" + currentSolrServerPort); //NON-NLS
378  commandLine.add("-DSTOP.KEY=" + KEY); //NON-NLS
379  commandLine.add("-jar"); //NON-NLS
380  commandLine.add("start.jar"); //NON-NLS
381 
382  commandLine.addAll(solrArguments);
383 
384  ProcessBuilder solrProcessBuilder = new ProcessBuilder(commandLine);
385  solrProcessBuilder.directory(solrFolder);
386 
387  // Redirect stdout and stderr to files to prevent blocking.
388  Path solrStdoutPath = Paths.get(Places.getUserDirectory().getAbsolutePath(), "var", "log", "solr.log.stdout"); //NON-NLS
389  solrProcessBuilder.redirectOutput(solrStdoutPath.toFile());
390 
391  Path solrStderrPath = Paths.get(Places.getUserDirectory().getAbsolutePath(), "var", "log", "solr.log.stderr"); //NON-NLS
392  solrProcessBuilder.redirectError(solrStderrPath.toFile());
393 
394  logger.log(Level.INFO, "Running Solr command: {0}", solrProcessBuilder.command()); //NON-NLS
395  Process process = solrProcessBuilder.start();
396  logger.log(Level.INFO, "Finished running Solr command"); //NON-NLS
397  return process;
398  }
399 
405  List<Long> getSolrPIDs() {
406  List<Long> pids = new ArrayList<>();
407 
408  //NOTE: these needs to be in sync with process start string in start()
409  final String pidsQuery = "Args.*.eq=-DSTOP.KEY=" + KEY + ",Args.*.eq=start.jar"; //NON-NLS
410 
411  long[] pidsArr = PlatformUtil.getJavaPIDs(pidsQuery);
412  if (pidsArr != null) {
413  for (int i = 0; i < pidsArr.length; ++i) {
414  pids.add(pidsArr[i]);
415  }
416  }
417 
418  return pids;
419  }
420 
425  void killSolr() {
426  List<Long> solrPids = getSolrPIDs();
427  for (long pid : solrPids) {
428  logger.log(Level.INFO, "Trying to kill old Solr process, PID: {0}", pid); //NON-NLS
429  PlatformUtil.killProcess(pid);
430  }
431  }
432 
438  @NbBundle.Messages({
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 {
441  if (isRunning()) {
442  // If a Solr server is running we stop it.
443  stop();
444  }
445 
446  if (!isPortAvailable(currentSolrServerPort)) {
447  // There is something already listening on our port. Let's see if
448  // this is from an earlier run that didn't successfully shut down
449  // and if so kill it.
450  final List<Long> pids = this.getSolrPIDs();
451 
452  // If the culprit listening on the port is not a Solr process
453  // we refuse to start.
454  if (pids.isEmpty()) {
455  throw new SolrServerNoPortException(currentSolrServerPort);
456  }
457 
458  // Ok, we've tried to stop it above but there still appears to be
459  // a Solr process listening on our port so we forcefully kill it.
460  killSolr();
461 
462  // If either of the ports are still in use after our attempt to kill
463  // previously running processes we give up and throw an exception.
464  if (!isPortAvailable(currentSolrServerPort)) {
465  throw new SolrServerNoPortException(currentSolrServerPort);
466  }
467  if (!isPortAvailable(currentSolrStopPort)) {
468  throw new SolrServerNoPortException(currentSolrStopPort);
469  }
470  }
471 
472  logger.log(Level.INFO, "Starting Solr server from: {0}", solrFolder.getAbsolutePath()); //NON-NLS
473 
474  if (isPortAvailable(currentSolrServerPort)) {
475  logger.log(Level.INFO, "Port [{0}] available, starting Solr", currentSolrServerPort); //NON-NLS
476  try {
477  curSolrProcess = runSolrCommand(new ArrayList<>(
478  Arrays.asList("-Dbootstrap_confdir=../solr/configsets/AutopsyConfig/conf", //NON-NLS
479  "-Dcollection.configName=AutopsyConfig"))); //NON-NLS
480 
481  // Wait for the Solr server to start and respond to a status request.
482  for (int numRetries = 0; numRetries < 6; numRetries++) {
483  if (isRunning()) {
484  final List<Long> pids = this.getSolrPIDs();
485  logger.log(Level.INFO, "New Solr process PID: {0}", pids); //NON-NLS
486  return;
487  }
488 
489  // Local Solr server did not respond so we sleep for
490  // 5 seconds before trying again.
491  try {
492  TimeUnit.SECONDS.sleep(5);
493  } catch (InterruptedException ex) {
494  logger.log(Level.WARNING, "Timer interrupted"); //NON-NLS
495  }
496  }
497 
498  // If we get here the Solr server has not responded to connection
499  // attempts in a timely fashion.
500  logger.log(Level.WARNING, "Local Solr server failed to respond to status requests.");
501  WindowManager.getDefault().invokeWhenUIReady(new Runnable() {
502  @Override
503  public void run() {
504  MessageNotifyUtil.Notify.error(
505  NbBundle.getMessage(this.getClass(), "Installer.errorInitKsmMsg"),
506  Bundle.Server_status_failed_msg());
507  }
508  });
509  } catch (SecurityException ex) {
510  logger.log(Level.SEVERE, "Could not start Solr process!", ex); //NON-NLS
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); //NON-NLS
515  throw new KeywordSearchModuleException(
516  NbBundle.getMessage(this.getClass(), "Server.start.exception.cantStartSolr.msg2"), ex);
517  }
518  }
519  }
520 
526  static boolean isPortAvailable(int port) {
527  ServerSocket ss = null;
528  try {
529 
530  ss = new ServerSocket(port, 0, java.net.Inet4Address.getByName("localhost")); //NON-NLS
531  if (ss.isBound()) {
532  ss.setReuseAddress(true);
533  ss.close();
534  return true;
535  }
536 
537  } catch (IOException e) {
538  } finally {
539  if (ss != null) {
540  try {
541  ss.close();
542  } catch (IOException e) {
543  /*
544  * should not be thrown
545  */
546  }
547  }
548  }
549  return false;
550  }
551 
557  void changeSolrServerPort(int port) {
558  currentSolrServerPort = port;
559  ModuleSettings.setConfigSetting(PROPERTIES_FILE, PROPERTIES_CURRENT_SERVER_PORT, String.valueOf(port));
560  }
561 
567  void changeSolrStopPort(int port) {
568  currentSolrStopPort = port;
569  ModuleSettings.setConfigSetting(PROPERTIES_FILE, PROPERTIES_CURRENT_STOP_PORT, String.valueOf(port));
570  }
571 
577  synchronized void stop() {
578 
579  try {
580  // Close any open core before stopping server
581  closeCore();
582  } catch (KeywordSearchModuleException e) {
583  logger.log(Level.WARNING, "Failed to close core: ", e); //NON-NLS
584  }
585 
586  try {
587  logger.log(Level.INFO, "Stopping Solr server from: {0}", solrFolder.getAbsolutePath()); //NON-NLS
588 
589  //try graceful shutdown
590  Process process = runSolrCommand(new ArrayList<>(Arrays.asList("--stop"))); //NON-NLS
591 
592  logger.log(Level.INFO, "Waiting for Solr server to stop"); //NON-NLS
593  process.waitFor();
594 
595  //if still running, forcefully stop it
596  if (curSolrProcess != null) {
597  curSolrProcess.destroy();
598  curSolrProcess = null;
599  }
600 
601  } catch (IOException | InterruptedException ex) {
602  logger.log(Level.WARNING, "Error while attempting to stop Solr server", ex);
603  } finally {
604  //stop Solr stream -> log redirect threads
605  try {
606  if (errorRedirectThread != null) {
607  errorRedirectThread.stopRun();
608  errorRedirectThread = null;
609  }
610  } finally {
611  //if still running, kill it
612  killSolr();
613  }
614 
615  logger.log(Level.INFO, "Finished stopping Solr server"); //NON-NLS
616  }
617  }
618 
626  synchronized boolean isRunning() throws KeywordSearchModuleException {
627  try {
628 
629  if (isPortAvailable(currentSolrServerPort)) {
630  return false;
631  }
632 
633  // making a status request here instead of just doing solrServer.ping(), because
634  // that doesn't work when there are no cores
635  //TODO handle timeout in cases when some other type of server on that port
636  connectToSolrServer(localSolrServer);
637 
638  logger.log(Level.INFO, "Solr server is running"); //NON-NLS
639  } catch (SolrServerException ex) {
640 
641  Throwable cause = ex.getRootCause();
642 
643  // TODO: check if SocketExceptions should actually happen (is
644  // probably caused by starting a connection as the server finishes
645  // shutting down)
646  if (cause instanceof ConnectException || cause instanceof SocketException) { //|| cause instanceof NoHttpResponseException) {
647  logger.log(Level.INFO, "Solr server is not running, cause: {0}", cause.getMessage()); //NON-NLS
648  return false;
649  } else {
650  throw new KeywordSearchModuleException(
651  NbBundle.getMessage(this.getClass(), "Server.isRunning.exception.errCheckSolrRunning.msg"), ex);
652  }
653  } catch (SolrException ex) {
654  // Just log 404 errors for now...
655  logger.log(Level.INFO, "Solr server is not running", ex); //NON-NLS
656  return false;
657  } catch (IOException ex) {
658  throw new KeywordSearchModuleException(
659  NbBundle.getMessage(this.getClass(), "Server.isRunning.exception.errCheckSolrRunning.msg2"), ex);
660  }
661 
662  return true;
663  }
664 
665  /*
666  * ** Convenience methods for use while we only open one case at a time ***
667  */
677  void openCoreForCase(Case theCase, Index index) throws KeywordSearchModuleException {
678  currentCoreLock.writeLock().lock();
679  try {
680  currentCore = openCore(theCase, index);
681 
682  try {
683  // execute a test query. if it fails, an exception will be thrown
685  } catch (NoOpenCoreException ex) {
686  throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.openCore.exception.cantOpen.msg"), ex);
687  }
688 
689  serverAction.putValue(CORE_EVT, CORE_EVT_STATES.STARTED);
690  } finally {
691  currentCoreLock.writeLock().unlock();
692  }
693  }
694 
700  boolean coreIsOpen() {
701  currentCoreLock.readLock().lock();
702  try {
703  return (null != currentCore);
704  } finally {
705  currentCoreLock.readLock().unlock();
706  }
707  }
708 
709  Index getIndexInfo() throws NoOpenCoreException {
710  currentCoreLock.readLock().lock();
711  try {
712  if (null == currentCore) {
713  throw new NoOpenCoreException();
714  }
715  return currentCore.getIndexInfo();
716  } finally {
717  currentCoreLock.readLock().unlock();
718  }
719  }
720 
721  void closeCore() throws KeywordSearchModuleException {
722  currentCoreLock.writeLock().lock();
723  try {
724  if (null != currentCore) {
725  currentCore.close();
726  currentCore = null;
727  serverAction.putValue(CORE_EVT, CORE_EVT_STATES.STOPPED);
728  }
729  } finally {
730  currentCoreLock.writeLock().unlock();
731  }
732  }
733 
734  void addDocument(SolrInputDocument doc) throws KeywordSearchModuleException, NoOpenCoreException {
735  currentCoreLock.readLock().lock();
736  try {
737  if (null == currentCore) {
738  throw new NoOpenCoreException();
739  }
740  TimingMetric metric = HealthMonitor.getTimingMetric("Solr: Index chunk");
741  currentCore.addDocument(doc);
742  HealthMonitor.submitTimingMetric(metric);
743  } finally {
744  currentCoreLock.readLock().unlock();
745  }
746  }
747 
756  @NbBundle.Messages({
757  "# {0} - core name", "Server.deleteCore.exception.msg=Failed to delete Solr core {0}",})
758  void deleteCore(String coreName, CaseMetadata metadata) throws KeywordSearchServiceException {
759  try {
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"); //NON-NLS
764  } else {
765  IndexingServerProperties properties = getMultiUserServerProperties(metadata.getCaseDirectory());
766  solrServer = new HttpSolrServer("http://" + properties.getHost() + ":" + properties.getPort() + "/solr"); //NON-NLS
767  }
768  connectToSolrServer(solrServer);
769  CoreAdminResponse response = CoreAdminRequest.getStatus(coreName, solrServer);
770  if (null != response.getCoreStatus(coreName).get("instanceDir")) { //NON-NLS
771  /*
772  * Send a core unload request to the Solr server, with the
773  * parameter set that request deleting the index and the
774  * instance directory (deleteInstanceDir = true). Note that this
775  * removes everything related to the core on the server (the
776  * index directory, the configuration files, etc.), but does not
777  * delete the actual Solr text index because it is currently
778  * stored in the case directory.
779  */
780  org.apache.solr.client.solrj.request.CoreAdminRequest.unloadCore(coreName, true, true, solrServer);
781  }
782  } catch (SolrServerException | HttpSolrServer.RemoteSolrException | IOException ex) {
783  // We will get a RemoteSolrException with cause == null and detailsMessage
784  // == "Already closed" if the core is not loaded. This is not an error in this scenario.
785  if (!ex.getMessage().equals("Already closed")) { // NON-NLS
786  throw new KeywordSearchServiceException(Bundle.Server_deleteCore_exception_msg(coreName), ex);
787  }
788  }
789  }
790 
802  private Core openCore(Case theCase, Index index) throws KeywordSearchModuleException {
803 
804  try {
805  if (theCase.getCaseType() == CaseType.SINGLE_USER_CASE) {
806  currentSolrServer = this.localSolrServer;
807  } else {
808  IndexingServerProperties properties = getMultiUserServerProperties(theCase.getCaseDirectory());
809  currentSolrServer = new HttpSolrServer("http://" + properties.getHost() + ":" + properties.getPort() + "/solr"); //NON-NLS
810  }
811  TimingMetric metric = HealthMonitor.getTimingMetric("Solr: Connectivity check");
812  connectToSolrServer(currentSolrServer);
814 
815  } catch (SolrServerException | IOException ex) {
816  throw new KeywordSearchModuleException(NbBundle.getMessage(Server.class, "Server.connect.exception.msg", ex.getLocalizedMessage()), ex);
817  }
818 
819  try {
820  File dataDir = new File(new File(index.getIndexPath()).getParent()); // "data dir" is the parent of the index directory
821  if (!dataDir.exists()) {
822  dataDir.mkdirs();
823  }
824 
825  if (!this.isRunning()) {
826  logger.log(Level.SEVERE, "Core create/open requested, but server not yet running"); //NON-NLS
827  throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.openCore.exception.msg"));
828  }
829 
830  String coreName = index.getIndexName();
831  if (!coreIsLoaded(coreName)) {
832  /*
833  * The core either does not exist or it is not loaded. Make a
834  * request that will cause the core to be created if it does not
835  * exist or loaded if it already exists.
836  */
837 
838  // In single user mode, if there is a core.properties file already,
839  // we've hit a solr bug. Compensate by deleting it.
840  if (theCase.getCaseType() == CaseType.SINGLE_USER_CASE) {
841  Path corePropertiesFile = Paths.get(solrFolder.toString(), SOLR, coreName, CORE_PROPERTIES);
842  if (corePropertiesFile.toFile().exists()) {
843  try {
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."); //NON-NLS
847  }
848  }
849  }
850 
851  CoreAdminRequest.Create createCoreRequest = new CoreAdminRequest.Create();
852  createCoreRequest.setDataDir(dataDir.getAbsolutePath());
853  createCoreRequest.setCoreName(coreName);
854  createCoreRequest.setConfigSet("AutopsyConfig"); //NON-NLS
855  createCoreRequest.setIsLoadOnStartup(false);
856  createCoreRequest.setIsTransient(true);
857  currentSolrServer.request(createCoreRequest);
858  }
859 
860  if (!coreIndexFolderExists(coreName)) {
861  throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.openCore.exception.noIndexDir.msg"));
862  }
863 
864  return new Core(coreName, theCase.getCaseType(), index);
865 
866  } catch (Exception ex) {
867  throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.openCore.exception.cantOpen.msg"), ex);
868  }
869  }
870 
879  public static IndexingServerProperties getMultiUserServerProperties(String caseDirectory) {
880 
881  Path serverFilePath = Paths.get(caseDirectory, "solrserver.txt");
882  if(serverFilePath.toFile().exists()){
883  try{
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));
889  } else {
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));
893  } else {
894  return new IndexingServerProperties(parts[0], parts[1]);
895  }
896  }
897  } catch (IOException ex) {
898  logger.log(Level.SEVERE, "solrserver.txt file could not be read", ex);
899  }
900  }
901 
902  // Default back to the user preferences if the solrserver.txt file was not found or if an error occurred
903  String host = UserPreferences.getIndexingServerHost();
904  String port = UserPreferences.getIndexingServerPort();
905  return new IndexingServerProperties(host, port);
906  }
907 
921  public static void selectSolrServerForCase(Path rootOutputDirectory, Path caseDirectoryPath) throws KeywordSearchModuleException {
922  // Look for the solr server list file
923  String serverListName = "solrServerList.txt";
924  Path serverListPath = Paths.get(rootOutputDirectory.toString(), serverListName);
925  if(serverListPath.toFile().exists()){
926 
927  // Read the list of solr servers
928  List<String> lines;
929  try{
930  lines = Files.readAllLines(serverListPath);
931  } catch (IOException ex){
932  throw new KeywordSearchModuleException(serverListName + " could not be read", ex);
933  }
934 
935  // Remove any lines that don't contain a comma (these are likely just whitespace)
936  for (Iterator<String> iterator = lines.iterator(); iterator.hasNext();) {
937  String line = iterator.next();
938  if (! line.contains(",")) {
939  // Remove the current element from the iterator and the list.
940  iterator.remove();
941  }
942  }
943  if(lines.isEmpty()) {
944  throw new KeywordSearchModuleException(serverListName + " had no valid server information");
945  }
946 
947  // Choose which server to use
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));
952  }
953 
954  // Split it up just to do a sanity check on the data
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));
959  }
960 
961  // Write the server data to a file
962  Path serverFile = Paths.get(caseDirectoryPath.toString(), "solrserver.txt");
963  try {
964  caseDirectoryPath.toFile().mkdirs();
965  if (! caseDirectoryPath.toFile().exists()) {
966  throw new KeywordSearchModuleException("Case directory " + caseDirectoryPath.toString() + " does not exist");
967  }
968  Files.write(serverFile, lines.get(rnd).getBytes());
969  } catch (IOException ex){
970  throw new KeywordSearchModuleException(serverFile.toString() + " could not be written", ex);
971  }
972  }
973  }
974 
978  public static class IndexingServerProperties {
979  private final String host;
980  private final String port;
981 
982  IndexingServerProperties (String host, String port) {
983  this.host = host;
984  this.port = port;
985  }
986 
991  public String getHost() {
992  return host;
993  }
994 
999  public String getPort() {
1000  return port;
1001  }
1002  }
1003 
1009  void commit() throws SolrServerException, NoOpenCoreException {
1010  currentCoreLock.readLock().lock();
1011  try {
1012  if (null == currentCore) {
1013  throw new NoOpenCoreException();
1014  }
1015  currentCore.commit();
1016  } finally {
1017  currentCoreLock.readLock().unlock();
1018  }
1019  }
1020 
1021  NamedList<Object> request(SolrRequest request) throws SolrServerException, NoOpenCoreException {
1022  currentCoreLock.readLock().lock();
1023  try {
1024  if (null == currentCore) {
1025  throw new NoOpenCoreException();
1026  }
1027  return currentCore.request(request);
1028  } finally {
1029  currentCoreLock.readLock().unlock();
1030  }
1031  }
1032 
1043  public int queryNumIndexedFiles() throws KeywordSearchModuleException, NoOpenCoreException {
1044  currentCoreLock.readLock().lock();
1045  try {
1046  if (null == currentCore) {
1047  throw new NoOpenCoreException();
1048  }
1049  try {
1050  return currentCore.queryNumIndexedFiles();
1051  } catch (SolrServerException | IOException ex) {
1052  throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.queryNumIdxFiles.exception.msg"), ex);
1053  }
1054  } finally {
1055  currentCoreLock.readLock().unlock();
1056  }
1057  }
1058 
1068  public int queryNumIndexedChunks() throws KeywordSearchModuleException, NoOpenCoreException {
1069  currentCoreLock.readLock().lock();
1070  try {
1071  if (null == currentCore) {
1072  throw new NoOpenCoreException();
1073  }
1074  try {
1075  return currentCore.queryNumIndexedChunks();
1076  } catch (SolrServerException | IOException ex) {
1077  throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.queryNumIdxChunks.exception.msg"), ex);
1078  }
1079  } finally {
1080  currentCoreLock.readLock().unlock();
1081  }
1082  }
1083 
1093  public int queryNumIndexedDocuments() throws KeywordSearchModuleException, NoOpenCoreException {
1094  currentCoreLock.readLock().lock();
1095  try {
1096  if (null == currentCore) {
1097  throw new NoOpenCoreException();
1098  }
1099  try {
1100  return currentCore.queryNumIndexedDocuments();
1101  } catch (SolrServerException | IOException ex) {
1102  throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.queryNumIdxDocs.exception.msg"), ex);
1103  }
1104  } finally {
1105  currentCoreLock.readLock().unlock();
1106  }
1107  }
1108 
1119  public boolean queryIsIndexed(long contentID) throws KeywordSearchModuleException, NoOpenCoreException {
1120  currentCoreLock.readLock().lock();
1121  try {
1122  if (null == currentCore) {
1123  throw new NoOpenCoreException();
1124  }
1125  try {
1126  return currentCore.queryIsIndexed(contentID);
1127  } catch (SolrServerException | IOException ex) {
1128  throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.queryIsIdxd.exception.msg"), ex);
1129  }
1130 
1131  } finally {
1132  currentCoreLock.readLock().unlock();
1133  }
1134  }
1135 
1147  public int queryNumFileChunks(long fileID) throws KeywordSearchModuleException, NoOpenCoreException {
1148  currentCoreLock.readLock().lock();
1149  try {
1150  if (null == currentCore) {
1151  throw new NoOpenCoreException();
1152  }
1153  try {
1154  return currentCore.queryNumFileChunks(fileID);
1155  } catch (SolrServerException | IOException ex) {
1156  throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.queryNumFileChunks.exception.msg"), ex);
1157  }
1158  } finally {
1159  currentCoreLock.readLock().unlock();
1160  }
1161  }
1162 
1173  public QueryResponse query(SolrQuery sq) throws KeywordSearchModuleException, NoOpenCoreException, IOException {
1174  currentCoreLock.readLock().lock();
1175  try {
1176  if (null == currentCore) {
1177  throw new NoOpenCoreException();
1178  }
1179  try {
1180  return currentCore.query(sq);
1181  } catch (SolrServerException ex) {
1182  logger.log(Level.SEVERE, "Solr query failed: " + sq.getQuery(), ex); //NON-NLS
1183  throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.query.exception.msg", sq.getQuery()), ex);
1184  }
1185  } finally {
1186  currentCoreLock.readLock().unlock();
1187  }
1188  }
1189 
1201  public QueryResponse query(SolrQuery sq, SolrRequest.METHOD method) throws KeywordSearchModuleException, NoOpenCoreException {
1202  currentCoreLock.readLock().lock();
1203  try {
1204  if (null == currentCore) {
1205  throw new NoOpenCoreException();
1206  }
1207  try {
1208  return currentCore.query(sq, method);
1209  } catch (SolrServerException | IOException ex) {
1210  logger.log(Level.SEVERE, "Solr query failed: " + sq.getQuery(), ex); //NON-NLS
1211  throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.query2.exception.msg", sq.getQuery()), ex);
1212  }
1213  } finally {
1214  currentCoreLock.readLock().unlock();
1215  }
1216  }
1217 
1228  public TermsResponse queryTerms(SolrQuery sq) throws KeywordSearchModuleException, NoOpenCoreException {
1229  currentCoreLock.readLock().lock();
1230  try {
1231  if (null == currentCore) {
1232  throw new NoOpenCoreException();
1233  }
1234  try {
1235  return currentCore.queryTerms(sq);
1236  } catch (SolrServerException | IOException ex) {
1237  logger.log(Level.SEVERE, "Solr terms query failed: " + sq.getQuery(), ex); //NON-NLS
1238  throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.queryTerms.exception.msg", sq.getQuery()), ex);
1239  }
1240  } finally {
1241  currentCoreLock.readLock().unlock();
1242  }
1243  }
1244 
1254  public String getSolrContent(final Content content) throws NoOpenCoreException {
1255  currentCoreLock.readLock().lock();
1256  try {
1257  if (null == currentCore) {
1258  throw new NoOpenCoreException();
1259  }
1260  return currentCore.getSolrContent(content.getId(), 0);
1261  } finally {
1262  currentCoreLock.readLock().unlock();
1263  }
1264  }
1265 
1278  public String getSolrContent(final Content content, int chunkID) throws NoOpenCoreException {
1279  currentCoreLock.readLock().lock();
1280  try {
1281  if (null == currentCore) {
1282  throw new NoOpenCoreException();
1283  }
1284  return currentCore.getSolrContent(content.getId(), chunkID);
1285  } finally {
1286  currentCoreLock.readLock().unlock();
1287  }
1288  }
1289 
1299  public String getSolrContent(final long objectID) throws NoOpenCoreException {
1300  currentCoreLock.readLock().lock();
1301  try {
1302  if (null == currentCore) {
1303  throw new NoOpenCoreException();
1304  }
1305  return currentCore.getSolrContent(objectID, 0);
1306  } finally {
1307  currentCoreLock.readLock().unlock();
1308  }
1309  }
1310 
1321  public String getSolrContent(final long objectID, final int chunkID) throws NoOpenCoreException {
1322  currentCoreLock.readLock().lock();
1323  try {
1324  if (null == currentCore) {
1325  throw new NoOpenCoreException();
1326  }
1327  return currentCore.getSolrContent(objectID, chunkID);
1328  } finally {
1329  currentCoreLock.readLock().unlock();
1330  }
1331  }
1332 
1342  public static String getChunkIdString(long parentID, int childID) {
1343  return Long.toString(parentID) + Server.CHUNK_ID_SEPARATOR + Integer.toString(childID);
1344  }
1345 
1354  void connectToSolrServer(HttpSolrServer solrServer) throws SolrServerException, IOException {
1355  TimingMetric metric = HealthMonitor.getTimingMetric("Solr: Connectivity check");
1356  CoreAdminRequest statusRequest = new CoreAdminRequest();
1357  statusRequest.setCoreName( null );
1358  statusRequest.setAction( CoreAdminParams.CoreAdminAction.STATUS );
1359  statusRequest.setIndexInfoNeeded(false);
1360  statusRequest.process(solrServer);
1362  }
1363 
1377  private boolean coreIsLoaded(String coreName) throws SolrServerException, IOException {
1378  CoreAdminResponse response = CoreAdminRequest.getStatus(coreName, currentSolrServer);
1379  return response.getCoreStatus(coreName).get("instanceDir") != null; //NON-NLS
1380  }
1381 
1392  private boolean coreIndexFolderExists(String coreName) throws SolrServerException, IOException {
1393  CoreAdminResponse response = CoreAdminRequest.getStatus(coreName, currentSolrServer);
1394  Object dataDirPath = response.getCoreStatus(coreName).get("dataDir"); //NON-NLS
1395  if (null != dataDirPath) {
1396  File indexDir = Paths.get((String) dataDirPath, "index").toFile(); //NON-NLS
1397  return indexDir.exists();
1398  } else {
1399  return false;
1400  }
1401  }
1402 
1403  class Core {
1404 
1405  // handle to the core in Solr
1406  private final String name;
1407 
1408  private final CaseType caseType;
1409 
1410  private final Index textIndex;
1411 
1412  // the server to access a core needs to be built from a URL with the
1413  // core in it, and is only good for core-specific operations
1414  private final HttpSolrServer solrCore;
1415 
1416  private final int QUERY_TIMEOUT_MILLISECONDS = 86400000; // 24 Hours = 86,400,000 Milliseconds
1417 
1418  private Core(String name, CaseType caseType, Index index) {
1419  this.name = name;
1420  this.caseType = caseType;
1421  this.textIndex = index;
1422 
1423  this.solrCore = new HttpSolrServer(currentSolrServer.getBaseURL() + "/" + name); //NON-NLS
1424 
1425  //TODO test these settings
1426  // socket read timeout, make large enough so can index larger files
1427  solrCore.setSoTimeout(QUERY_TIMEOUT_MILLISECONDS);
1428  //solrCore.setConnectionTimeout(1000);
1429  solrCore.setDefaultMaxConnectionsPerHost(32);
1430  solrCore.setMaxTotalConnections(32);
1431  solrCore.setFollowRedirects(false); // defaults to false
1432  // allowCompression defaults to false.
1433  // Server side must support gzip or deflate for this to have any effect.
1434  solrCore.setAllowCompression(true);
1435  solrCore.setParser(new XMLResponseParser()); // binary parser is used by default
1436 
1437  }
1438 
1444  String getName() {
1445  return name;
1446  }
1447 
1448  private Index getIndexInfo() {
1449  return this.textIndex;
1450  }
1451 
1452  private QueryResponse query(SolrQuery sq) throws SolrServerException, IOException {
1453  return solrCore.query(sq);
1454  }
1455 
1456  private NamedList<Object> request(SolrRequest request) throws SolrServerException {
1457  try {
1458  return solrCore.request(request);
1459  } catch (IOException e) {
1460  logger.log(Level.WARNING, "Could not issue Solr request. ", e); //NON-NLS
1461  throw new SolrServerException(
1462  NbBundle.getMessage(this.getClass(), "Server.request.exception.exception.msg"), e);
1463  }
1464 
1465  }
1466 
1467  private QueryResponse query(SolrQuery sq, SolrRequest.METHOD method) throws SolrServerException, IOException {
1468  return solrCore.query(sq, method);
1469  }
1470 
1471  private TermsResponse queryTerms(SolrQuery sq) throws SolrServerException, IOException {
1472  QueryResponse qres = solrCore.query(sq);
1473  return qres.getTermsResponse();
1474  }
1475 
1476  private void commit() throws SolrServerException {
1477  try {
1478  //commit and block
1479  solrCore.commit(true, true);
1480  } catch (IOException e) {
1481  logger.log(Level.WARNING, "Could not commit index. ", e); //NON-NLS
1482  throw new SolrServerException(NbBundle.getMessage(this.getClass(), "Server.commit.exception.msg"), e);
1483  }
1484  }
1485 
1486  void addDocument(SolrInputDocument doc) throws KeywordSearchModuleException {
1487  try {
1488  solrCore.add(doc);
1489  } catch (SolrServerException ex) {
1490  logger.log(Level.SEVERE, "Could not add document to index via update handler: " + doc.getField("id"), ex); //NON-NLS
1491  throw new KeywordSearchModuleException(
1492  NbBundle.getMessage(this.getClass(), "Server.addDoc.exception.msg", doc.getField("id")), ex); //NON-NLS
1493  } catch (IOException ex) {
1494  logger.log(Level.SEVERE, "Could not add document to index via update handler: " + doc.getField("id"), ex); //NON-NLS
1495  throw new KeywordSearchModuleException(
1496  NbBundle.getMessage(this.getClass(), "Server.addDoc.exception.msg2", doc.getField("id")), ex); //NON-NLS
1497  }
1498  }
1499 
1509  private String getSolrContent(long contentID, int chunkID) {
1510  final SolrQuery q = new SolrQuery();
1511  q.setQuery("*:*");
1512  String filterQuery = Schema.ID.toString() + ":" + KeywordSearchUtil.escapeLuceneQuery(Long.toString(contentID));
1513  if (chunkID != 0) {
1514  filterQuery = filterQuery + Server.CHUNK_ID_SEPARATOR + chunkID;
1515  }
1516  q.addFilterQuery(filterQuery);
1517  q.setFields(Schema.TEXT.toString());
1518  try {
1519  // Get the first result.
1520  SolrDocumentList solrDocuments = solrCore.query(q).getResults();
1521 
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) // The indexed text field for artifacts will only have a single value.
1527  {
1528  return fieldValues.toArray(new String[0])[0];
1529  } else // The indexed text for files has 2 values, the file name and the file content.
1530  // We return the file content value.
1531  {
1532  return fieldValues.toArray(new String[0])[1];
1533  }
1534  }
1535  }
1536  } catch (SolrServerException ex) {
1537  logger.log(Level.SEVERE, "Error getting content from Solr. Solr document id " + contentID + ", chunk id " + chunkID + ", query: " + filterQuery, ex); //NON-NLS
1538  return null;
1539  }
1540 
1541  return null;
1542  }
1543 
1544  synchronized void close() throws KeywordSearchModuleException {
1545  // We only unload cores for "single-user" cases.
1546  if (this.caseType == CaseType.MULTI_USER_CASE) {
1547  return;
1548  }
1549 
1550  try {
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);
1558  }
1559  }
1560 
1570  private int queryNumIndexedFiles() throws SolrServerException, IOException {
1572  }
1573 
1583  private int queryNumIndexedChunks() throws SolrServerException, IOException {
1584  SolrQuery q = new SolrQuery(Server.Schema.ID + ":*" + Server.CHUNK_ID_SEPARATOR + "*");
1585  q.setRows(0);
1586  int numChunks = (int) query(q).getResults().getNumFound();
1587  return numChunks;
1588  }
1589 
1600  private int queryNumIndexedDocuments() throws SolrServerException, IOException {
1601  SolrQuery q = new SolrQuery("*:*");
1602  q.setRows(0);
1603  return (int) query(q).getResults().getNumFound();
1604  }
1605 
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);
1619  //q.setFields(Server.Schema.ID.toString());
1620  q.setRows(0);
1621  return (int) query(q).getResults().getNumFound() != 0;
1622  }
1623 
1635  private int queryNumFileChunks(long contentID) throws SolrServerException, IOException {
1636  String id = KeywordSearchUtil.escapeLuceneQuery(Long.toString(contentID));
1637  final SolrQuery q
1638  = new SolrQuery(Server.Schema.ID + ":" + id + Server.CHUNK_ID_SEPARATOR + "*");
1639  q.setRows(0);
1640  return (int) query(q).getResults().getNumFound();
1641  }
1642  }
1643 
1644  class ServerAction extends AbstractAction {
1645 
1646  private static final long serialVersionUID = 1L;
1647 
1648  @Override
1649  public void actionPerformed(ActionEvent e) {
1650  logger.log(Level.INFO, e.paramString().trim());
1651  }
1652  }
1653 
1657  class SolrServerNoPortException extends SocketException {
1658 
1659  private static final long serialVersionUID = 1L;
1660 
1664  private final int port;
1665 
1666  SolrServerNoPortException(int port) {
1667  super(NbBundle.getMessage(Server.class, "Server.solrServerNoPortException.msg", port,
1668  Server.PROPERTIES_CURRENT_SERVER_PORT));
1669  this.port = port;
1670  }
1671 
1672  int getPortNumber() {
1673  return port;
1674  }
1675  }
1676 }
String getSolrContent(final long objectID)
Definition: Server.java:1299
final ReentrantReadWriteLock currentCoreLock
Definition: Server.java:218
static IndexingServerProperties getMultiUserServerProperties(String caseDirectory)
Definition: Server.java:879
boolean coreIsLoaded(String coreName)
Definition: Server.java:1377
static TimingMetric getTimingMetric(String name)
static void selectSolrServerForCase(Path rootOutputDirectory, Path caseDirectoryPath)
Definition: Server.java:921
void addServerActionListener(PropertyChangeListener l)
Definition: Server.java:285
static final String HL_ANALYZE_CHARS_UNLIMITED
Definition: Server.java:181
Process runSolrCommand(List< String > solrArguments)
Definition: Server.java:370
String getSolrContent(final Content content)
Definition: Server.java:1254
boolean coreIndexFolderExists(String coreName)
Definition: Server.java:1392
static synchronized void setConfigSetting(String moduleName, String settingName, String settingVal)
static final Charset DEFAULT_INDEXED_TEXT_CHARSET
default Charset to index text as
Definition: Server.java:190
InputStreamPrinterThread errorRedirectThread
Definition: Server.java:223
QueryResponse query(SolrQuery sq)
Definition: Server.java:1173
static String getConfigSetting(String moduleName, String settingName)
static synchronized String getJavaPath()
static void submitTimingMetric(TimingMetric metric)
TermsResponse queryTerms(SolrQuery sq)
Definition: Server.java:1228
boolean queryIsIndexed(long contentID)
Definition: Server.java:1119
String getSolrContent(final Content content, int chunkID)
Definition: Server.java:1278
String getSolrContent(final long objectID, final int chunkID)
Definition: Server.java:1321
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
static synchronized long[] getJavaPIDs(String sigarSubQuery)
Core openCore(Case theCase, Index index)
Definition: Server.java:802
static String getChunkIdString(long parentID, int childID)
Definition: Server.java:1342
static boolean settingExists(String moduleName, String settingName)
QueryResponse query(SolrQuery sq, SolrRequest.METHOD method)
Definition: Server.java:1201

Copyright © 2012-2018 Basis Technology. Generated on: Wed Sep 18 2019
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.