From 79d00eedb3d9eb8c038aa7431d23206279c15ec3 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Thu, 19 Jan 2017 16:33:07 -0500 Subject: [PATCH 1/8] Clean up Index class --- .../autopsy/keywordsearch/Index.java | 33 ++----------------- .../autopsy/keywordsearch/IndexFinder.java | 4 +-- .../keywordsearch/SolrSearchService.java | 11 +++---- 3 files changed, 9 insertions(+), 39 deletions(-) diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Index.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Index.java index 67cba2aaf2..af8a79ddf8 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Index.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Index.java @@ -23,15 +23,9 @@ package org.sleuthkit.autopsy.keywordsearch; */ class Index { - private String indexPath; - private String schemaVersion; - private String solrVersion; - - Index() { - this.indexPath = ""; - this.solrVersion = ""; - this.schemaVersion = ""; - } + private final String indexPath; + private final String schemaVersion; + private final String solrVersion; Index(String indexPath, String solrVersion, String schemaVersion) { this.indexPath = indexPath; @@ -46,13 +40,6 @@ class Index { return indexPath; } - /** - * @param indexPath the indexPath to set - */ - void setIndexPath(String indexPath) { - this.indexPath = indexPath; - } - /** * @return the schemaVersion */ @@ -60,26 +47,12 @@ class Index { return schemaVersion; } - /** - * @param schemaVersion the schemaVersion to set - */ - void setSchemaVersion(String schemaVersion) { - this.schemaVersion = schemaVersion; - } - /** * @return the solrVersion */ String getSolrVersion() { return solrVersion; } - - /** - * @param solrVersion the solrVersion to set - */ - void setSolrVersion(String solrVersion) { - this.solrVersion = solrVersion; - } /** * @param true if all Index fields are set, false otherwise diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/IndexFinder.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/IndexFinder.java index 9502da5c76..3e7a7c4ec7 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/IndexFinder.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/IndexFinder.java @@ -73,7 +73,7 @@ class IndexFinder { return index; } } - return new Index(); + return null; } static Index createLatestVersionIndexDir(Case theCase) { @@ -91,7 +91,7 @@ class IndexFinder { X:\Case\ingest4\ModuleOutput\keywordsearch\data\solr6_schema_1.8\index X:\Case\ingest4\ModuleOutput\keywordsearch\data\solr7_schema_2.0\index */ - Index bestCandidateIndex = new Index(); + Index bestCandidateIndex = null; double solrVerFound = 0.0; double schemaVerFound = 0.0; for (Index index : allIndexes) { diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java index 4f6f4525c7..0fffe2f2aa 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java @@ -168,11 +168,10 @@ public class SolrSearchService implements KeywordSearchService, AutopsyService } else { // check if one of the existing indexes is for latest Solr version and schema currentVersionIndex = IndexFinder.findLatestVersionIndexDir(indexes); - - if (!currentVersionIndex.isIndexDataPopulated()) { + if (currentVersionIndex == null) { // found existing index(es) but none were for latest Solr version and schema version Index indexToUpgrade = IndexFinder.identifyIndexToUpgrade(indexes); - if (!indexToUpgrade.isIndexDataPopulated()) { + if (indexToUpgrade == null) { // unable to find index that can be upgraded throw new AutopsyServiceException("Unable to find index that can be upgraded to the latest version of Solr"); } @@ -181,7 +180,7 @@ public class SolrSearchService implements KeywordSearchService, AutopsyService double indexSolrVersion = NumberUtils.toDouble(indexToUpgrade.getSolrVersion()); if (indexSolrVersion > currentSolrVersion) { // oops! - throw new AutopsyServiceException("Unable to find index that can be upgraded to the latest version of Solr"); + throw new AutopsyServiceException("Unable to find index to use for Case open"); } else if (indexSolrVersion == currentSolrVersion) { // latest Solr version but not latest schema. index should be used in read-only mode and not be upgraded. @@ -220,9 +219,7 @@ public class SolrSearchService implements KeywordSearchService, AutopsyService indexUpgrader.performIndexUpgrade(indexToUpgrade, context.getCase().getTempDirectory()); // set the upgraded index as the index to be used for this case - currentVersionIndex.setIndexPath(newIndexDir); - currentVersionIndex.setSolrVersion(IndexFinder.getCurrentSolrVersion()); - currentVersionIndex.setSchemaVersion(indexToUpgrade.getSchemaVersion()); + currentVersionIndex = new Index(newIndexDir, IndexFinder.getCurrentSolrVersion(), indexToUpgrade.getSchemaVersion()); } } } From 056bf25a2ddf7da5c89ff32292747fad10921678 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Thu, 19 Jan 2017 17:40:06 -0500 Subject: [PATCH 2/8] Keeping track of new Solr cores and creating names for them --- .../autopsy/keywordsearch/Index.java | 18 ++- .../autopsy/keywordsearch/Server.java | 142 +++++++++--------- .../keywordsearch/SolrSearchService.java | 2 + 3 files changed, 91 insertions(+), 71 deletions(-) diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Index.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Index.java index af8a79ddf8..b8a76869b5 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Index.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Index.java @@ -26,12 +26,14 @@ class Index { private final String indexPath; private final String schemaVersion; private final String solrVersion; + private boolean newIndex; Index(String indexPath, String solrVersion, String schemaVersion) { this.indexPath = indexPath; this.solrVersion = solrVersion; this.schemaVersion = schemaVersion; - } + newIndex = false; + } /** * @return the indexPath @@ -63,4 +65,18 @@ class Index { } return false; } + + /** + * @return the newIndex + */ + boolean isNewIndex() { + return newIndex; + } + + /** + * @param newIndex the newIndex to set + */ + void setNewIndex(boolean newIndex) { + this.newIndex = newIndex; + } } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Server.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Server.java index 2c8d44c5b2..acc8e4d2d3 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Server.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Server.java @@ -36,9 +36,11 @@ import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Date; import java.util.List; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.logging.Level; @@ -724,7 +726,7 @@ public class Server { * creating/opening the core. */ private Core openCore(Case theCase, Index index) throws KeywordSearchModuleException { - + try { if (theCase.getCaseType() == CaseType.SINGLE_USER_CASE) { currentSolrServer = this.localSolrServer; @@ -739,8 +741,75 @@ public class Server { throw new KeywordSearchModuleException(NbBundle.getMessage(Server.class, "Server.connect.exception.msg"), ex); } - String coreName = theCase.getTextIndexName(); - return this.openCore(coreName.isEmpty() ? DEFAULT_CORE_NAME : coreName, index, theCase.getCaseType()); + try { + CaseType caseType = theCase.getCaseType(); + String coreName; + if (index.isNewIndex()) { + // come up with a new core name + coreName = createCoreName(theCase.getName()); + } else { + // ELTODO get core name + coreName = ""; + } + + File dataDir = new File(new File(index.getIndexPath()).getParent()); // "data dir" is the parent of the index directory + if (!dataDir.exists()) { + dataDir.mkdirs(); + } + + if (!this.isRunning()) { + logger.log(Level.SEVERE, "Core create/open requested, but server not yet running"); //NON-NLS + throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.openCore.exception.msg")); + } + + if (!coreIsLoaded(coreName)) { + /* + * The core either does not exist or it is not loaded. Make a + * request that will cause the core to be created if it does not + * exist or loaded if it already exists. + */ + + // In single user mode, if there is a core.properties file already, + // we've hit a solr bug. Compensate by deleting it. + if (caseType == CaseType.SINGLE_USER_CASE) { + Path corePropertiesFile = Paths.get(solrFolder.toString(), SOLR, coreName, CORE_PROPERTIES); + if (corePropertiesFile.toFile().exists()) { + try { + corePropertiesFile.toFile().delete(); + } catch (Exception ex) { + logger.log(Level.INFO, "Could not delete pre-existing core.properties prior to opening the core."); //NON-NLS + } + } + } + + CoreAdminRequest.Create createCoreRequest = new CoreAdminRequest.Create(); + createCoreRequest.setDataDir(dataDir.getAbsolutePath()); + createCoreRequest.setCoreName(coreName); + createCoreRequest.setConfigSet("AutopsyConfig"); //NON-NLS + createCoreRequest.setIsLoadOnStartup(false); + createCoreRequest.setIsTransient(true); + currentSolrServer.request(createCoreRequest); + } + + if (!coreIndexFolderExists(coreName)) { + throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.openCore.exception.noIndexDir.msg")); + } + + return new Core(coreName, caseType, index); + + } catch (SolrServerException | SolrException | IOException ex) { + throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.openCore.exception.cantOpen.msg"), ex); + } + } + + private String createCoreName(String caseName) { + if (caseName.isEmpty()) { + caseName = DEFAULT_CORE_NAME; + } + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss"); + Date date = new Date(); + String coreName = caseName + "_" + dateFormat.format(date); + return coreName; } /** @@ -1083,73 +1152,6 @@ public class Server { return Long.toString(parentID) + Server.CHUNK_ID_SEPARATOR + Integer.toString(childID); } - /** - * Creates/opens a Solr core (index) for a case. - * - * @param coreName The core name. - * @param index The text index object for the core. - * @param caseType The type of the case (single-user or multi-user) for - * which the core is being created/opened. - * - * @return An object representing the created/opened core. - * - * @throws KeywordSearchModuleException If an error occurs while - * creating/opening the core. - */ - private Core openCore(String coreName, Index index, CaseType caseType) throws KeywordSearchModuleException { - - try { - - File dataDir = new File(new File(index.getIndexPath()).getParent()); // "data dir" is the parent of the index directory - if (!dataDir.exists()) { - dataDir.mkdirs(); - } - - if (!this.isRunning()) { - logger.log(Level.SEVERE, "Core create/open requested, but server not yet running"); //NON-NLS - throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.openCore.exception.msg")); - } - - if (!coreIsLoaded(coreName)) { - /* - * The core either does not exist or it is not loaded. Make a - * request that will cause the core to be created if it does not - * exist or loaded if it already exists. - */ - - // In single user mode, if there is a core.properties file already, - // we've hit a solr bug. Compensate by deleting it. - if (caseType == CaseType.SINGLE_USER_CASE) { - Path corePropertiesFile = Paths.get(solrFolder.toString(), SOLR, coreName, CORE_PROPERTIES); - if (corePropertiesFile.toFile().exists()) { - try { - corePropertiesFile.toFile().delete(); - } catch (Exception ex) { - logger.log(Level.INFO, "Could not delete pre-existing core.properties prior to opening the core."); //NON-NLS - } - } - } - - CoreAdminRequest.Create createCoreRequest = new CoreAdminRequest.Create(); - createCoreRequest.setDataDir(dataDir.getAbsolutePath()); - createCoreRequest.setCoreName(coreName); - createCoreRequest.setConfigSet("AutopsyConfig"); //NON-NLS - createCoreRequest.setIsLoadOnStartup(false); - createCoreRequest.setIsTransient(true); - currentSolrServer.request(createCoreRequest); - } - - if (!coreIndexFolderExists(coreName)) { - throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.openCore.exception.noIndexDir.msg")); - } - - return new Core(coreName, caseType, index); - - } catch (SolrServerException | SolrException | IOException ex) { - throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.openCore.exception.cantOpen.msg"), ex); - } - } - /** * Attempts to connect to the given Solr server. * diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java index 0fffe2f2aa..c0bd936368 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java @@ -165,6 +165,7 @@ public class SolrSearchService implements KeywordSearchService, AutopsyService if (indexes.isEmpty()) { // new case that doesn't have an existing index. create new index folder currentVersionIndex = IndexFinder.createLatestVersionIndexDir(context.getCase()); + currentVersionIndex.setNewIndex(true); } else { // check if one of the existing indexes is for latest Solr version and schema currentVersionIndex = IndexFinder.findLatestVersionIndexDir(indexes); @@ -220,6 +221,7 @@ public class SolrSearchService implements KeywordSearchService, AutopsyService // set the upgraded index as the index to be used for this case currentVersionIndex = new Index(newIndexDir, IndexFinder.getCurrentSolrVersion(), indexToUpgrade.getSchemaVersion()); + currentVersionIndex.setNewIndex(true); } } } From af5199df4bd809c4d60c145bbfe36635de057ddd Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Fri, 20 Jan 2017 13:29:05 -0500 Subject: [PATCH 3/8] Creating, sanitizing, and storing Solr core names --- .../sleuthkit/autopsy/casemodule/Case.java | 22 +++-- .../autopsy/casemodule/CaseMetadata.java | 20 +++- .../casemodule/SingleUserCaseConverter.java | 3 +- .../autopsy/keywordsearch/Server.java | 94 ++++++++++++++++--- .../keywordsearch/SolrSearchService.java | 2 + 5 files changed, 117 insertions(+), 24 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index cd984c2155..cf5a02a0e4 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -662,6 +662,18 @@ public class Case implements SleuthkitCase.ErrorObserver { public String getTextIndexName() { return getCaseMetadata().getTextIndexName(); } + + /** + * Sets the name of the keyword search index for the case. + * + * @param indexName The index name. + * + * @throws + * org.sleuthkit.autopsy.casemodule.CaseMetadata.CaseMetadataException + */ + public void setTextIndexName(String indexName) throws CaseMetadataException { + caseMetadata.setTextIndexName(indexName); + } /** * Queries whether or not the case has data, i.e., whether or not at least @@ -984,19 +996,17 @@ public class Case implements SleuthkitCase.ErrorObserver { } /* - * Sanitize the case name, create a unique keyword search index name, - * and create a standard (single-user) or unique (multi-user) case - * database name. + * Sanitize the case name, and create a standard (single-user) or + * unique (multi-user) case database name. */ String santizedCaseName = sanitizeCaseName(caseName); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss"); Date date = new Date(); - String indexName = santizedCaseName + "_" + dateFormat.format(date); String dbName = null; if (caseType == CaseType.SINGLE_USER_CASE) { dbName = caseDir + File.separator + "autopsy.db"; //NON-NLS } else if (caseType == CaseType.MULTI_USER_CASE) { - dbName = indexName; + dbName = santizedCaseName + "_" + dateFormat.format(date); } try{ @@ -1037,7 +1047,7 @@ public class Case implements SleuthkitCase.ErrorObserver { */ CaseMetadata metadata; try { - metadata = new CaseMetadata(caseDir, caseType, caseName, caseNumber, examiner, dbName, indexName); + metadata = new CaseMetadata(caseDir, caseType, caseName, caseNumber, examiner, dbName); } catch (CaseMetadataException ex) { throw new CaseActionException(Bundle.Case_creationException(), ex); } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java index bd07a3deaf..19e62db1d2 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java @@ -102,19 +102,17 @@ public final class CaseMetadata { * @param caseDatabase For a single-user case, the full path to the * case database file. For a multi-user case, the * case database name. - * @param caseTextIndexName The text index name. * * @throws CaseMetadataException If the new case metadata file cannot be * created. */ - CaseMetadata(String caseDirectory, Case.CaseType caseType, String caseName, String caseNumber, String examiner, String caseDatabase, String caseTextIndexName) throws CaseMetadataException { + CaseMetadata(String caseDirectory, Case.CaseType caseType, String caseName, String caseNumber, String examiner, String caseDatabase) throws CaseMetadataException { metadataFilePath = Paths.get(caseDirectory, caseName + FILE_EXTENSION); this.caseType = caseType; this.caseName = caseName; this.caseNumber = caseNumber; this.examiner = examiner; this.caseDatabase = caseDatabase; - this.textIndexName = caseTextIndexName; createdByVersion = Version.getVersion(); createdDate = CaseMetadata.DATE_FORMAT.format(new Date()); writeToFile(); @@ -186,6 +184,22 @@ public final class CaseMetadata { throw ex; } } + + /** + * Sets the text index name. + * + * @param caseTextIndexName The text index name. + */ + void setTextIndexName(String caseTextIndexName) throws CaseMetadataException { + String oldIndexName = caseTextIndexName; + this.textIndexName = caseTextIndexName; + try { + writeToFile(); + } catch (CaseMetadataException ex) { + this.textIndexName = oldIndexName; + throw ex; + } + } /** * Gets the case number. diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/SingleUserCaseConverter.java b/Core/src/org/sleuthkit/autopsy/casemodule/SingleUserCaseConverter.java index e39f0d5ebb..31e655838d 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/SingleUserCaseConverter.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/SingleUserCaseConverter.java @@ -176,7 +176,6 @@ public class SingleUserCaseConverter { SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss"); //NON-NLS Date date = new Date(); String dbName = Case.sanitizeCaseName(icd.getNewCaseName()) + "_" + dateFormat.format(date); //NON-NLS - String solrName = dbName; icd.setPostgreSQLDbName(dbName); // Copy items to new hostname folder structure @@ -197,7 +196,7 @@ public class SingleUserCaseConverter { icd.getNewCaseName(), oldCaseMetadata.getCaseNumber(), oldCaseMetadata.getExaminer(), - dbName, solrName); + dbName); // Set created date. This calls writefile, no need to call it again newCaseMetadata.setCreatedDate(oldCaseMetadata.getCreatedDate()); newCaseMetadata.setCreatedByVersion(oldCaseMetadata.getCreatedByVersion()); diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Server.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Server.java index acc8e4d2d3..c35bd01117 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Server.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Server.java @@ -65,6 +65,7 @@ import org.openide.modules.Places; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case.CaseType; +import org.sleuthkit.autopsy.casemodule.CaseMetadata; import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ModuleSettings; @@ -742,15 +743,7 @@ public class Server { } try { - CaseType caseType = theCase.getCaseType(); - String coreName; - if (index.isNewIndex()) { - // come up with a new core name - coreName = createCoreName(theCase.getName()); - } else { - // ELTODO get core name - coreName = ""; - } + String coreName = getCoreName(index, theCase); File dataDir = new File(new File(index.getIndexPath()).getParent()); // "data dir" is the parent of the index directory if (!dataDir.exists()) { @@ -771,7 +764,7 @@ public class Server { // In single user mode, if there is a core.properties file already, // we've hit a solr bug. Compensate by deleting it. - if (caseType == CaseType.SINGLE_USER_CASE) { + if (theCase.getCaseType() == CaseType.SINGLE_USER_CASE) { Path corePropertiesFile = Paths.get(solrFolder.toString(), SOLR, coreName, CORE_PROPERTIES); if (corePropertiesFile.toFile().exists()) { try { @@ -795,13 +788,48 @@ public class Server { throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.openCore.exception.noIndexDir.msg")); } - return new Core(coreName, caseType, index); + return new Core(coreName, theCase.getCaseType(), index); - } catch (SolrServerException | SolrException | IOException ex) { + } catch (SolrServerException | SolrException | IOException | CaseMetadata.CaseMetadataException ex) { throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.openCore.exception.cantOpen.msg"), ex); } } + /** + * Get or create a sanitized Solr core name. Stores the core name if needed. + * + * @param index Index object + * @param theCase Case object + * + * @return The sanitized Solr core name + */ + private String getCoreName(Index index, Case theCase) throws CaseMetadata.CaseMetadataException { + String coreName = ""; + if (index.isNewIndex()) { + // come up with a new core name + coreName = createCoreName(theCase.getName()); + // store the new core name + theCase.setTextIndexName(coreName); + } else { + // get core name + coreName = theCase.getTextIndexName(); + if (coreName.isEmpty()) { + // come up with a new core name + coreName = createCoreName(theCase.getName()); + // store the new core name + theCase.setTextIndexName(coreName); + } + } + return coreName; + } + + /** + * Create and sanitize a core name. + * + * @param caseName Case name + * + * @return The sanitized Solr core name + */ private String createCoreName(String caseName) { if (caseName.isEmpty()) { caseName = DEFAULT_CORE_NAME; @@ -809,7 +837,47 @@ public class Server { SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss"); Date date = new Date(); String coreName = caseName + "_" + dateFormat.format(date); - return coreName; + return sanitizeCoreName(coreName); + } + + /** + * Sanitizes the case name for Solr cores. + * + * Solr: + * http://stackoverflow.com/questions/29977519/what-makes-an-invalid-core-name + * may not be / \ : + * Starting Solr6: core names must consist entirely of periods, underscores, hyphens, and alphanumerics as well not start with a hyphen. may not contain space characters. + * + * @param coreName A candidate core name. + * + * @return The sanitized core name. + */ + static private String sanitizeCoreName(String coreName) { + + String result; + + // Remove all non-ASCII characters + result = coreName.replaceAll("[^\\p{ASCII}]", "_"); //NON-NLS + + // Remove all control characters + result = result.replaceAll("[\\p{Cntrl}]", "_"); //NON-NLS + + // Remove spaces / \ : ? ' " + result = result.replaceAll("[ /?:'\"\\\\]", "_"); //NON-NLS + + // Make it all lowercase + result = result.toLowerCase(); + + // Must not start with hyphen + if (result.length() > 0 && !(Character.isLetter(result.codePointAt(0))) && !(result.codePointAt(0) == '-')) { + result = "_" + result; + } + + if (result.isEmpty()) { + result = DEFAULT_CORE_NAME; + } + + return result; } /** diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java index c0bd936368..0d7672950c 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java @@ -196,6 +196,8 @@ public class SolrSearchService implements KeywordSearchService, AutopsyService } // proceed with case open currentVersionIndex = indexToUpgrade; + + currentVersionIndex.setNewIndex(true);// ELTODO remove } else { // index needs to be upgraded to latest supported version of Solr From 12783887b2171b6e86bb427f689bb614d33d9929 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Fri, 20 Jan 2017 14:13:04 -0500 Subject: [PATCH 4/8] Minor --- .../org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java index 0d7672950c..c0bd936368 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java @@ -196,8 +196,6 @@ public class SolrSearchService implements KeywordSearchService, AutopsyService } // proceed with case open currentVersionIndex = indexToUpgrade; - - currentVersionIndex.setNewIndex(true);// ELTODO remove } else { // index needs to be upgraded to latest supported version of Solr From bcdd2a628b910674f8fdec80ad38d2f791b8c77a Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Fri, 20 Jan 2017 14:20:51 -0500 Subject: [PATCH 5/8] More cleanup --- .../src/org/sleuthkit/autopsy/keywordsearch/Index.java | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Index.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Index.java index b8a76869b5..e979474352 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Index.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Index.java @@ -55,16 +55,6 @@ class Index { String getSolrVersion() { return solrVersion; } - - /** - * @param true if all Index fields are set, false otherwise - */ - boolean isIndexDataPopulated() { - if (!this.indexPath.isEmpty() && !this.solrVersion.isEmpty() && !this.schemaVersion.isEmpty()) { - return true; - } - return false; - } /** * @return the newIndex From b936df4cd69d8720bfeea4bea3f5ee831c12c27a Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Fri, 20 Jan 2017 15:09:08 -0500 Subject: [PATCH 6/8] Minor --- .../src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties | 1 + .../org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties index 2bf824795e..2241785a23 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties @@ -313,6 +313,7 @@ GlobalEditListPanel.keywordDupesSkipped.text={0} keyword was already in the list GlobalEditListPanel.keywordDupesSkippedPlural.text={0} keywords were already in the list. GlobalEditListPanel.keywordErrors.text={0} keyword could not be parsed. Please review and try again. GlobalEditListPanel.keywordErrorsPlural.text={0} keywords could not be parsed. Please review and try again. +SolrSearchService.ServiceName=Solr Keyword Search Service SolrSearchService.IndexUpgradeDialog.title=Text Index Upgrade Required In Order To Open Case SolrSearchService.IndexUpgradeDialog.msg=The text index upgrade can take some time.
When completed, you will be able to see existing keyword search results and perform literal keyword searches,
but you will not be able to add new text to the index or perform regex searches. You may instead open the case
with your previous version of this application. Do you wish to proceed with the index upgrade? SolrSearchService.IndexReadOnlyDialog.title=Text Index Is Read-Only diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java index c0bd936368..75ccfe38af 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java @@ -52,7 +52,6 @@ public class SolrSearchService implements KeywordSearchService, AutopsyService private static final String BAD_IP_ADDRESS_FORMAT = "ioexception occurred when talking to server"; //NON-NLS private static final String SERVER_REFUSED_CONNECTION = "server refused connection"; //NON-NLS private static final int IS_REACHABLE_TIMEOUT_MS = 1000; - private static final String SERVICE_NAME = "Solr Keyword Search Service"; ArtifactTextExtractor extractor = new ArtifactTextExtractor(); @@ -272,6 +271,6 @@ public class SolrSearchService implements KeywordSearchService, AutopsyService @Override public String getServiceName() { - return SERVICE_NAME; + return NbBundle.getMessage(this.getClass(), "SolrSearchService.ServiceName"); } } From 7364f6ae0a32f87983b206e20ed520f0c31a050e Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Fri, 20 Jan 2017 15:21:19 -0500 Subject: [PATCH 7/8] Execute a test query after core is opened, throw exception if faled --- .../src/org/sleuthkit/autopsy/keywordsearch/Server.java | 8 ++++++++ .../autopsy/keywordsearch/SolrSearchService.java | 3 --- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Server.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Server.java index c35bd01117..b4949ea976 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Server.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Server.java @@ -670,6 +670,14 @@ public class Server { currentCoreLock.writeLock().lock(); try { currentCore = openCore(theCase, index); + + try { + // execute a test query. if it fails, an exception will be thrown + queryNumIndexedFiles(); + } catch (NoOpenCoreException ex) { + throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.openCore.exception.cantOpen.msg"), ex); + } + serverAction.putValue(CORE_EVT, CORE_EVT_STATES.STARTED); } finally { currentCoreLock.writeLock().unlock(); diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java index 75ccfe38af..d436300bcc 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SolrSearchService.java @@ -234,9 +234,6 @@ public class SolrSearchService implements KeywordSearchService, AutopsyService MessageNotifyUtil.Notify.error(NbBundle.getMessage(KeywordSearch.class, "KeywordSearch.openCore.notification.msg"), ex.getMessage()); } } - - // ELTODO execute a test query - // ELTODO if failed, close the upgraded index? } /** From 577ad27b61761ab374ecf4d54685b9fb917147ca Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Fri, 20 Jan 2017 15:22:26 -0500 Subject: [PATCH 8/8] Cleanup --- .../src/org/sleuthkit/autopsy/keywordsearch/Server.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Server.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Server.java index b4949ea976..79c91b82ab 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Server.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Server.java @@ -191,8 +191,7 @@ public class Server { private int currentSolrServerPort = 0; private int currentSolrStopPort = 0; private static final boolean DEBUG = false;//(Version.getBuildType() == Version.Type.DEVELOPMENT); - private UNCPathUtilities uncPathUtilities = null; - private static final String SOLR = "solr"; + private static final String SOLR = "solr"; private static final String CORE_PROPERTIES = "core.properties"; public enum CORE_EVT_STATES { @@ -260,7 +259,6 @@ public class Server { } } currentCoreLock = new ReentrantReadWriteLock(true); - uncPathUtilities = new UNCPathUtilities(); logger.log(Level.INFO, "Created Server instance using Java at {0}", javaHome); //NON-NLS }