Interim commit - isolated scheme creation code from DBSettings classes and put them in the new RdmsCentralRepoSchemaFactory.

This commit is contained in:
Raman Arora 2020-02-06 16:25:06 -05:00
parent ab81c1fe79
commit cc7ed224ff
8 changed files with 757 additions and 625 deletions

View File

@ -131,7 +131,10 @@ final class PostgresCentralRepo extends RdbmsCentralRepo {
CentralRepoDbUtil.closeConnection(conn); CentralRepoDbUtil.closeConnection(conn);
} }
dbSettings.insertDefaultDatabaseContent();
//dbSettings.insertDefaultDatabaseContent();
RdbmsCentralRepoSchemaFactory centralRepoSchemaFactory = new RdbmsCentralRepoSchemaFactory(CentralRepoPlatforms.POSTGRESQL);
centralRepoSchemaFactory.insertDefaultDatabaseContent();
} }
/** /**
@ -209,6 +212,10 @@ final class PostgresCentralRepo extends RdbmsCentralRepo {
return CONFLICT_CLAUSE; return CONFLICT_CLAUSE;
} }
@Override
protected Connection getEphemeralConnection() {
return this.dbSettings.getEphemeralConnection(false);
}
/** /**
* Gets an exclusive lock (if applicable). Will return the lock if * Gets an exclusive lock (if applicable). Will return the lock if
* successful, null if unsuccessful because locking isn't supported, and * successful, null if unsuccessful because locking isn't supported, and

View File

@ -162,7 +162,7 @@ public final class PostgresCentralRepoSettings {
* *
* @return Connection or null. * @return Connection or null.
*/ */
private Connection getEphemeralConnection(boolean usePostgresDb) { Connection getEphemeralConnection(boolean usePostgresDb) {
Connection conn; Connection conn;
try { try {
String url = getConnectionURL(usePostgresDb); String url = getConnectionURL(usePostgresDb);
@ -290,308 +290,25 @@ public final class PostgresCentralRepoSettings {
} }
/**
* Initialize the database schema.
*
* Requires valid connectionPool.
*
* This method is called from within connect(), so we cannot call connect()
* to get a connection. This method is called after setupConnectionPool(),
* so it is safe to assume that a valid connectionPool exists. The
* implementation of connect() is synchronized, so we can safely use the
* connectionPool object directly.
*/
public boolean initializeDatabaseSchema() {
// The "id" column is an alias for the built-in 64-bit int "rowid" column.
// It is autoincrementing by default and must be of type "integer primary key".
// We've omitted the autoincrement argument because we are not currently
// using the id value to search for specific rows, so we do not care
// if a rowid is re-used after an existing rows was previously deleted.
StringBuilder createOrganizationsTable = new StringBuilder();
createOrganizationsTable.append("CREATE TABLE IF NOT EXISTS organizations (");
createOrganizationsTable.append("id SERIAL PRIMARY KEY,");
createOrganizationsTable.append("org_name text NOT NULL,");
createOrganizationsTable.append("poc_name text NOT NULL,");
createOrganizationsTable.append("poc_email text NOT NULL,");
createOrganizationsTable.append("poc_phone text NOT NULL,");
createOrganizationsTable.append("CONSTRAINT org_name_unique UNIQUE (org_name)");
createOrganizationsTable.append(")");
// NOTE: The organizations will only have a small number of rows, so
// an index is probably not worthwhile.
StringBuilder createCasesTable = new StringBuilder();
createCasesTable.append("CREATE TABLE IF NOT EXISTS cases (");
createCasesTable.append("id SERIAL PRIMARY KEY,");
createCasesTable.append("case_uid text NOT NULL,");
createCasesTable.append("org_id integer,");
createCasesTable.append("case_name text NOT NULL,");
createCasesTable.append("creation_date text NOT NULL,");
createCasesTable.append("case_number text,");
createCasesTable.append("examiner_name text,");
createCasesTable.append("examiner_email text,");
createCasesTable.append("examiner_phone text,");
createCasesTable.append("notes text,");
createCasesTable.append("foreign key (org_id) references organizations(id) ON UPDATE SET NULL ON DELETE SET NULL,");
createCasesTable.append("CONSTRAINT case_uid_unique UNIQUE (case_uid)");
createCasesTable.append(")");
// NOTE: when there are few cases in the cases table, these indices may not be worthwhile
String casesIdx1 = "CREATE INDEX IF NOT EXISTS cases_org_id ON cases (org_id)";
String casesIdx2 = "CREATE INDEX IF NOT EXISTS cases_case_uid ON cases (case_uid)";
StringBuilder createReferenceSetsTable = new StringBuilder();
createReferenceSetsTable.append("CREATE TABLE IF NOT EXISTS reference_sets (");
createReferenceSetsTable.append("id SERIAL PRIMARY KEY,");
createReferenceSetsTable.append("org_id integer NOT NULL,");
createReferenceSetsTable.append("set_name text NOT NULL,");
createReferenceSetsTable.append("version text NOT NULL,");
createReferenceSetsTable.append("known_status integer NOT NULL,");
createReferenceSetsTable.append("read_only boolean NOT NULL,");
createReferenceSetsTable.append("type integer NOT NULL,");
createReferenceSetsTable.append("import_date text NOT NULL,");
createReferenceSetsTable.append("foreign key (org_id) references organizations(id) ON UPDATE SET NULL ON DELETE SET NULL,");
createReferenceSetsTable.append("CONSTRAINT hash_set_unique UNIQUE (set_name, version)");
createReferenceSetsTable.append(")");
String referenceSetsIdx1 = "CREATE INDEX IF NOT EXISTS reference_sets_org_id ON reference_sets (org_id)";
// Each "%s" will be replaced with the relevant reference_TYPE table name.
StringBuilder createReferenceTypesTableTemplate = new StringBuilder();
createReferenceTypesTableTemplate.append("CREATE TABLE IF NOT EXISTS %s (");
createReferenceTypesTableTemplate.append("id SERIAL PRIMARY KEY,");
createReferenceTypesTableTemplate.append("reference_set_id integer,");
createReferenceTypesTableTemplate.append("value text NOT NULL,");
createReferenceTypesTableTemplate.append("known_status integer NOT NULL,");
createReferenceTypesTableTemplate.append("comment text,");
createReferenceTypesTableTemplate.append("CONSTRAINT %s_multi_unique UNIQUE (reference_set_id, value),");
createReferenceTypesTableTemplate.append("foreign key (reference_set_id) references reference_sets(id) ON UPDATE SET NULL ON DELETE SET NULL");
createReferenceTypesTableTemplate.append(")");
// Each "%s" will be replaced with the relevant reference_TYPE table name.
String referenceTypesIdx1 = "CREATE INDEX IF NOT EXISTS %s_value ON %s (value)";
String referenceTypesIdx2 = "CREATE INDEX IF NOT EXISTS %s_value_known_status ON %s (value, known_status)";
StringBuilder createCorrelationTypesTable = new StringBuilder();
createCorrelationTypesTable.append("CREATE TABLE IF NOT EXISTS correlation_types (");
createCorrelationTypesTable.append("id SERIAL PRIMARY KEY,");
createCorrelationTypesTable.append("display_name text NOT NULL,");
createCorrelationTypesTable.append("db_table_name text NOT NULL,");
createCorrelationTypesTable.append("supported integer NOT NULL,");
createCorrelationTypesTable.append("enabled integer NOT NULL,");
createCorrelationTypesTable.append("CONSTRAINT correlation_types_names UNIQUE (display_name, db_table_name)");
createCorrelationTypesTable.append(")");
String createArtifactInstancesTableTemplate = getCreateArtifactInstancesTableTemplate();
String instancesCaseIdIdx = getAddCaseIdIndexTemplate();
String instancesDatasourceIdIdx = getAddDataSourceIdIndexTemplate();
String instancesValueIdx = getAddValueIndexTemplate();
String instancesKnownStatusIdx = getAddKnownStatusIndexTemplate();
String instancesObjectIdIdx = getAddObjectIdIndexTemplate();
// NOTE: the db_info table currenly only has 1 row, so having an index
// provides no benefit.
Connection conn = null;
try {
conn = getEphemeralConnection(false);
if (null == conn) {
return false;
}
Statement stmt = conn.createStatement();
stmt.execute(createOrganizationsTable.toString());
stmt.execute(createCasesTable.toString());
stmt.execute(casesIdx1);
stmt.execute(casesIdx2);
stmt.execute(getCreateDataSourcesTableStatement());
stmt.execute(getAddDataSourcesNameIndexStatement());
stmt.execute(getAddDataSourcesObjectIdIndexStatement());
stmt.execute(createReferenceSetsTable.toString());
stmt.execute(referenceSetsIdx1);
stmt.execute(createCorrelationTypesTable.toString());
/*
* Note that the essentially useless id column in the following
* table is required for backwards compatibility. Otherwise, the
* name column could be the primary key.
*/
stmt.execute("CREATE TABLE db_info (id SERIAL, name TEXT UNIQUE NOT NULL, value TEXT NOT NULL)");
stmt.execute("INSERT INTO db_info (name, value) VALUES ('" + RdbmsCentralRepo.SCHEMA_MAJOR_VERSION_KEY + "', '" + SOFTWARE_CR_DB_SCHEMA_VERSION.getMajor() + "')");
stmt.execute("INSERT INTO db_info (name, value) VALUES ('" + RdbmsCentralRepo.SCHEMA_MINOR_VERSION_KEY + "', '" + SOFTWARE_CR_DB_SCHEMA_VERSION.getMinor() + "')");
stmt.execute("INSERT INTO db_info (name, value) VALUES ('" + RdbmsCentralRepo.CREATION_SCHEMA_MAJOR_VERSION_KEY + "', '" + SOFTWARE_CR_DB_SCHEMA_VERSION.getMajor() + "')");
stmt.execute("INSERT INTO db_info (name, value) VALUES ('" + RdbmsCentralRepo.CREATION_SCHEMA_MINOR_VERSION_KEY + "', '" + SOFTWARE_CR_DB_SCHEMA_VERSION.getMinor() + "')");
// Create a separate instance and reference table for each correlation type
List<CorrelationAttributeInstance.Type> DEFAULT_CORRELATION_TYPES = CorrelationAttributeInstance.getDefaultCorrelationTypes();
String reference_type_dbname;
String instance_type_dbname;
for (CorrelationAttributeInstance.Type type : DEFAULT_CORRELATION_TYPES) {
reference_type_dbname = CentralRepoDbUtil.correlationTypeToReferenceTableName(type);
instance_type_dbname = CentralRepoDbUtil.correlationTypeToInstanceTableName(type);
stmt.execute(String.format(createArtifactInstancesTableTemplate, instance_type_dbname, instance_type_dbname));
stmt.execute(String.format(instancesCaseIdIdx, instance_type_dbname, instance_type_dbname));
stmt.execute(String.format(instancesDatasourceIdIdx, instance_type_dbname, instance_type_dbname));
stmt.execute(String.format(instancesValueIdx, instance_type_dbname, instance_type_dbname));
stmt.execute(String.format(instancesKnownStatusIdx, instance_type_dbname, instance_type_dbname));
stmt.execute(String.format(instancesObjectIdIdx, instance_type_dbname, instance_type_dbname));
// FUTURE: allow more than the FILES type
if (type.getId() == CorrelationAttributeInstance.FILES_TYPE_ID) {
stmt.execute(String.format(createReferenceTypesTableTemplate.toString(), reference_type_dbname, reference_type_dbname));
stmt.execute(String.format(referenceTypesIdx1, reference_type_dbname, reference_type_dbname));
stmt.execute(String.format(referenceTypesIdx2, reference_type_dbname, reference_type_dbname));
}
}
} catch (SQLException ex) {
LOGGER.log(Level.SEVERE, "Error initializing db schema.", ex); // NON-NLS
return false;
} catch (CentralRepoException ex) {
LOGGER.log(Level.SEVERE, "Error getting default correlation types. Likely due to one or more Type's with an invalid db table name."); // NON-NLS
return false;
} finally {
CentralRepoDbUtil.closeConnection(conn);
}
return true;
}
/**
* Get the template String for creating a new _instances table in a Postgres
* central repository. %s will exist in the template where the name of the
* new table will be addedd.
*
* @return a String which is a template for cretating a new _instances table
*/
static String getCreateArtifactInstancesTableTemplate() {
// Each "%s" will be replaced with the relevant TYPE_instances table name.
return ("CREATE TABLE IF NOT EXISTS %s (id SERIAL PRIMARY KEY,case_id integer NOT NULL,"
+ "data_source_id integer NOT NULL,value text NOT NULL,file_path text NOT NULL,"
+ "known_status integer NOT NULL,comment text,file_obj_id BIGINT,"
+ "CONSTRAINT %s_multi_unique_ UNIQUE (data_source_id, value, file_path),"
+ "foreign key (case_id) references cases(id) ON UPDATE SET NULL ON DELETE SET NULL,"
+ "foreign key (data_source_id) references data_sources(id) ON UPDATE SET NULL ON DELETE SET NULL)");
}
/**
* Get the statement String for creating a new data_sources table in a
* Postgres central repository.
*
* @return a String which is a statement for cretating a new data_sources
* table
*/
static String getCreateDataSourcesTableStatement() {
return "CREATE TABLE IF NOT EXISTS data_sources "
+ "(id SERIAL PRIMARY KEY,case_id integer NOT NULL,device_id text NOT NULL,"
+ "name text NOT NULL,datasource_obj_id BIGINT,md5 text DEFAULT NULL,"
+ "sha1 text DEFAULT NULL,sha256 text DEFAULT NULL,"
+ "foreign key (case_id) references cases(id) ON UPDATE SET NULL ON DELETE SET NULL,"
+ "CONSTRAINT datasource_unique UNIQUE (case_id, datasource_obj_id))";
}
/**
* Get the statement for creating an index on the name column of the
* data_sources table.
*
* @return a String which is a statement for adding an index on the name
* column of the data_sources table.
*/
static String getAddDataSourcesNameIndexStatement() {
return "CREATE INDEX IF NOT EXISTS data_sources_name ON data_sources (name)";
}
/**
* Get the statement for creating an index on the data_sources_object_id
* column of the data_sources table.
*
* @return a String which is a statement for adding an index on the
* data_sources_object_id column of the data_sources table.
*/
static String getAddDataSourcesObjectIdIndexStatement() {
return "CREATE INDEX IF NOT EXISTS data_sources_object_id ON data_sources (datasource_obj_id)";
}
/**
* Get the template for creating an index on the case_id column of an
* instance table. %s will exist in the template where the name of the new
* table will be addedd.
*
* @return a String which is a template for adding an index to the case_id
* column of a _instances table
*/
static String getAddCaseIdIndexTemplate() {
// Each "%s" will be replaced with the relevant TYPE_instances table name.
return "CREATE INDEX IF NOT EXISTS %s_case_id ON %s (case_id)";
}
/**
* Get the template for creating an index on the data_source_id column of an
* instance table. %s will exist in the template where the name of the new
* table will be addedd.
*
* @return a String which is a template for adding an index to the
* data_source_id column of a _instances table
*/
static String getAddDataSourceIdIndexTemplate() {
// Each "%s" will be replaced with the relevant TYPE_instances table name.
return "CREATE INDEX IF NOT EXISTS %s_data_source_id ON %s (data_source_id)";
}
/**
* Get the template for creating an index on the value column of an instance
* table. %s will exist in the template where the name of the new table will
* be addedd.
*
* @return a String which is a template for adding an index to the value
* column of a _instances table
*/
static String getAddValueIndexTemplate() {
// Each "%s" will be replaced with the relevant TYPE_instances table name.
return "CREATE INDEX IF NOT EXISTS %s_value ON %s (value)";
}
/**
* Get the template for creating an index on the known_status column of an
* instance table. %s will exist in the template where the name of the new
* table will be addedd.
*
* @return a String which is a template for adding an index to the
* known_status column of a _instances table
*/
static String getAddKnownStatusIndexTemplate() {
// Each "%s" will be replaced with the relevant TYPE_instances table name.
return "CREATE INDEX IF NOT EXISTS %s_value_known_status ON %s (value, known_status)";
}
/**
* Get the template for creating an index on the file_obj_id column of an
* instance table. %s will exist in the template where the name of the new
* table will be addedd.
*
* @return a String which is a template for adding an index to the
* file_obj_id column of a _instances table
*/
static String getAddObjectIdIndexTemplate() {
// Each "%s" will be replaced with the relevant TYPE_instances table name.
return "CREATE INDEX IF NOT EXISTS %s_file_obj_id ON %s (file_obj_id)";
}
public boolean insertDefaultDatabaseContent() {
Connection conn = getEphemeralConnection(false);
if (null == conn) {
return false;
}
boolean result = CentralRepoDbUtil.insertDefaultCorrelationTypes(conn) && CentralRepoDbUtil.insertDefaultOrganization(conn);
CentralRepoDbUtil.closeConnection(conn);
return result;
}
boolean isChanged() { boolean isChanged() {
String hostString = ModuleSettings.getConfigSetting("CentralRepository", "db.postgresql.host"); // NON-NLS String hostString = ModuleSettings.getConfigSetting("CentralRepository", "db.postgresql.host"); // NON-NLS

View File

@ -116,6 +116,10 @@ abstract class RdbmsCentralRepo implements CentralRepository {
*/ */
protected abstract Connection connect() throws CentralRepoException; protected abstract Connection connect() throws CentralRepoException;
/**
* Get an ephemeral connection.
*/
protected abstract Connection getEphemeralConnection();
/** /**
* Add a new name/value pair in the db_info table. * Add a new name/value pair in the db_info table.
* *
@ -3414,22 +3418,23 @@ abstract class RdbmsCentralRepo implements CentralRepository {
case POSTGRESQL: case POSTGRESQL:
addAttributeSql = "INSERT INTO correlation_types(id, display_name, db_table_name, supported, enabled) VALUES (?, ?, ?, ?, ?) " + getConflictClause(); //NON-NLS addAttributeSql = "INSERT INTO correlation_types(id, display_name, db_table_name, supported, enabled) VALUES (?, ?, ?, ?, ?) " + getConflictClause(); //NON-NLS
addSsidTableTemplate = PostgresCentralRepoSettings.getCreateArtifactInstancesTableTemplate(); // RAMAN TBD: get these from RdbmsCentralRepoSchemaFactory
addCaseIdIndexTemplate = PostgresCentralRepoSettings.getAddCaseIdIndexTemplate(); addSsidTableTemplate = RdbmsCentralRepoSchemaFactory.PostgresCRSchemaCreator.getCreateArtifactInstancesTableTemplate();
addDataSourceIdIndexTemplate = PostgresCentralRepoSettings.getAddDataSourceIdIndexTemplate(); addCaseIdIndexTemplate = RdbmsCentralRepoSchemaFactory.PostgresCRSchemaCreator.getAddCaseIdIndexTemplate();
addValueIndexTemplate = PostgresCentralRepoSettings.getAddValueIndexTemplate(); addDataSourceIdIndexTemplate = RdbmsCentralRepoSchemaFactory.PostgresCRSchemaCreator.getAddDataSourceIdIndexTemplate();
addKnownStatusIndexTemplate = PostgresCentralRepoSettings.getAddKnownStatusIndexTemplate(); addValueIndexTemplate = RdbmsCentralRepoSchemaFactory.PostgresCRSchemaCreator.getAddValueIndexTemplate();
addObjectIdIndexTemplate = PostgresCentralRepoSettings.getAddObjectIdIndexTemplate(); addKnownStatusIndexTemplate = RdbmsCentralRepoSchemaFactory.PostgresCRSchemaCreator.getAddKnownStatusIndexTemplate();
addObjectIdIndexTemplate = RdbmsCentralRepoSchemaFactory.PostgresCRSchemaCreator.getAddObjectIdIndexTemplate();
break; break;
case SQLITE: case SQLITE:
addAttributeSql = "INSERT OR IGNORE INTO correlation_types(id, display_name, db_table_name, supported, enabled) VALUES (?, ?, ?, ?, ?)"; //NON-NLS addAttributeSql = "INSERT OR IGNORE INTO correlation_types(id, display_name, db_table_name, supported, enabled) VALUES (?, ?, ?, ?, ?)"; //NON-NLS
addSsidTableTemplate = SqliteCentralRepoSettings.getCreateArtifactInstancesTableTemplate(); addSsidTableTemplate = RdbmsCentralRepoSchemaFactory.SQLiteCRSchemaCreator.getCreateArtifactInstancesTableTemplate();
addCaseIdIndexTemplate = SqliteCentralRepoSettings.getAddCaseIdIndexTemplate(); addCaseIdIndexTemplate = RdbmsCentralRepoSchemaFactory.SQLiteCRSchemaCreator.getAddCaseIdIndexTemplate();
addDataSourceIdIndexTemplate = SqliteCentralRepoSettings.getAddDataSourceIdIndexTemplate(); addDataSourceIdIndexTemplate = RdbmsCentralRepoSchemaFactory.SQLiteCRSchemaCreator.getAddDataSourceIdIndexTemplate();
addValueIndexTemplate = SqliteCentralRepoSettings.getAddValueIndexTemplate(); addValueIndexTemplate = RdbmsCentralRepoSchemaFactory.SQLiteCRSchemaCreator.getAddValueIndexTemplate();
addKnownStatusIndexTemplate = SqliteCentralRepoSettings.getAddKnownStatusIndexTemplate(); addKnownStatusIndexTemplate = RdbmsCentralRepoSchemaFactory.SQLiteCRSchemaCreator.getAddKnownStatusIndexTemplate();
addObjectIdIndexTemplate = SqliteCentralRepoSettings.getAddObjectIdIndexTemplate(); addObjectIdIndexTemplate = RdbmsCentralRepoSchemaFactory.SQLiteCRSchemaCreator.getAddObjectIdIndexTemplate();
break; break;
default: default:
throw new CentralRepoException("Currently selected database platform \"" + selectedPlatform.name() + "\" can not be upgraded.", Bundle.AbstractSqlEamDb_cannotUpgrage_message(selectedPlatform.name())); throw new CentralRepoException("Currently selected database platform \"" + selectedPlatform.name() + "\" can not be upgraded.", Bundle.AbstractSqlEamDb_cannotUpgrage_message(selectedPlatform.name()));
@ -3586,8 +3591,8 @@ abstract class RdbmsCentralRepo implements CentralRepository {
+ "md5 text DEFAULT NULL,sha1 text DEFAULT NULL,sha256 text DEFAULT NULL," + "md5 text DEFAULT NULL,sha1 text DEFAULT NULL,sha256 text DEFAULT NULL,"
+ "foreign key (case_id) references cases(id) ON UPDATE SET NULL ON DELETE SET NULL," + "foreign key (case_id) references cases(id) ON UPDATE SET NULL ON DELETE SET NULL,"
+ "CONSTRAINT datasource_unique UNIQUE (case_id, device_id, name, datasource_obj_id))"); + "CONSTRAINT datasource_unique UNIQUE (case_id, device_id, name, datasource_obj_id))");
statement.execute(SqliteCentralRepoSettings.getAddDataSourcesNameIndexStatement()); statement.execute(RdbmsCentralRepoSchemaFactory.SQLiteCRSchemaCreator.getAddDataSourcesNameIndexStatement());
statement.execute(SqliteCentralRepoSettings.getAddDataSourcesObjectIdIndexStatement()); statement.execute(RdbmsCentralRepoSchemaFactory.SQLiteCRSchemaCreator.getAddDataSourcesObjectIdIndexStatement());
statement.execute("INSERT INTO data_sources SELECT * FROM old_data_sources"); statement.execute("INSERT INTO data_sources SELECT * FROM old_data_sources");
statement.execute("DROP TABLE old_data_sources"); statement.execute("DROP TABLE old_data_sources");
break; break;

View File

@ -0,0 +1,696 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.sleuthkit.autopsy.centralrepository.datamodel;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import java.util.logging.Level;
import static org.sleuthkit.autopsy.centralrepository.datamodel.RdbmsCentralRepo.SOFTWARE_CR_DB_SCHEMA_VERSION;
import org.sleuthkit.autopsy.coreutils.Logger;
//import static org.sleuthkit.autopsy.centralrepository.datamodel.SqliteCentralRepoSettings.getCreateArtifactInstancesTableTemplate;
/**
* Creates the CR schema and populates it with initial data.
*
*/
public class RdbmsCentralRepoSchemaFactory {
private final static Logger LOGGER = Logger.getLogger(RdbmsCentralRepoSchemaFactory.class.getName());
private static RdbmsCentralRepoSchemaFactory instance;
private final RdbmsCentralRepo rdbmsCentralRepo;
private final CentralRepoPlatforms selectedPlatform;
// SQLite pragmas
private final static String PRAGMA_SYNC_OFF = "PRAGMA synchronous = OFF";
private final static String PRAGMA_SYNC_NORMAL = "PRAGMA synchronous = NORMAL";
private final static String PRAGMA_JOURNAL_WAL = "PRAGMA journal_mode = WAL";
private final static String PRAGMA_READ_UNCOMMITTED_TRUE = "PRAGMA read_uncommitted = True";
private final static String PRAGMA_ENCODING_UTF8 = "PRAGMA encoding = 'UTF-8'";
private final static String PRAGMA_PAGE_SIZE_4096 = "PRAGMA page_size = 4096";
private final static String PRAGMA_FOREIGN_KEYS_ON = "PRAGMA foreign_keys = ON";
/**
* Returns instance of singleton.
*
* @throws CentralRepoException
*/
// public static RdbmsCentralRepoSchemaFactory getInstance() throws CentralRepoException {
//
// if (instance == null) {
// instance = new RdbmsCentralRepoSchemaFactory();
// }
//
// return instance;
// }
public RdbmsCentralRepoSchemaFactory(CentralRepoPlatforms selectedPlatform) throws CentralRepoException {
//CentralRepoPlatforms selectedPlatform = CentralRepoPlatforms.DISABLED;
//if (CentralRepoDbUtil.allowUseOfCentralRepository()) {
// selectedPlatform = CentralRepoPlatforms.getSelectedPlatform();
//}
this.selectedPlatform = selectedPlatform;
switch (selectedPlatform) {
case POSTGRESQL:
rdbmsCentralRepo = PostgresCentralRepo.getInstance();
break;
case SQLITE:
rdbmsCentralRepo = SqliteCentralRepo.getInstance();
break;
default:
throw new CentralRepoException("Central Repo platform disabled.");
}
}
public boolean initializeDatabaseSchema() {
switch (selectedPlatform) {
case POSTGRESQL:
// RAMAN TBD
return PostgresCRSchemaCreator.initializeDatabaseSchema(rdbmsCentralRepo);
//break;
case SQLITE:
return SQLiteCRSchemaCreator.initializeDatabaseSchema(rdbmsCentralRepo);
//break;
default:
return false;
}
}
// TBD RAMAN - temporary container to store all SQLite methods, till we unify...
public static class SQLiteCRSchemaCreator {
/**
* Initialize the database schema.
*
* Requires valid connectionPool.
*
* This method is called from within connect(), so we cannot call
* connect() to get a connection. This method is called after
* setupConnectionPool(), so it is safe to assume that a valid
* connectionPool exists. The implementation of connect() is
* synchronized, so we can safely use the connectionPool object
* directly.
*/
public static boolean initializeDatabaseSchema(RdbmsCentralRepo rdbmsCentralRepo) {
// The "id" column is an alias for the built-in 64-bit int "rowid" column.
// It is autoincrementing by default and must be of type "integer primary key".
// We've omitted the autoincrement argument because we are not currently
// using the id value to search for specific rows, so we do not care
// if a rowid is re-used after an existing rows was previously deleted.
StringBuilder createOrganizationsTable = new StringBuilder();
createOrganizationsTable.append("CREATE TABLE IF NOT EXISTS organizations (");
createOrganizationsTable.append("id integer primary key autoincrement NOT NULL,");
createOrganizationsTable.append("org_name text NOT NULL,");
createOrganizationsTable.append("poc_name text NOT NULL,");
createOrganizationsTable.append("poc_email text NOT NULL,");
createOrganizationsTable.append("poc_phone text NOT NULL,");
createOrganizationsTable.append("CONSTRAINT org_name_unique UNIQUE (org_name)");
createOrganizationsTable.append(")");
// NOTE: The organizations will only have a small number of rows, so
// an index is probably not worthwhile.
StringBuilder createCasesTable = new StringBuilder();
createCasesTable.append("CREATE TABLE IF NOT EXISTS cases (");
createCasesTable.append("id integer primary key autoincrement NOT NULL,");
createCasesTable.append("case_uid text NOT NULL,");
createCasesTable.append("org_id integer,");
createCasesTable.append("case_name text NOT NULL,");
createCasesTable.append("creation_date text NOT NULL,");
createCasesTable.append("case_number text,");
createCasesTable.append("examiner_name text,");
createCasesTable.append("examiner_email text,");
createCasesTable.append("examiner_phone text,");
createCasesTable.append("notes text,");
createCasesTable.append("CONSTRAINT case_uid_unique UNIQUE(case_uid) ON CONFLICT IGNORE,");
createCasesTable.append("foreign key (org_id) references organizations(id) ON UPDATE SET NULL ON DELETE SET NULL");
createCasesTable.append(")");
// NOTE: when there are few cases in the cases table, these indices may not be worthwhile
String casesIdx1 = "CREATE INDEX IF NOT EXISTS cases_org_id ON cases (org_id)";
String casesIdx2 = "CREATE INDEX IF NOT EXISTS cases_case_uid ON cases (case_uid)";
StringBuilder createReferenceSetsTable = new StringBuilder();
createReferenceSetsTable.append("CREATE TABLE IF NOT EXISTS reference_sets (");
createReferenceSetsTable.append("id integer primary key autoincrement NOT NULL,");
createReferenceSetsTable.append("org_id integer NOT NULL,");
createReferenceSetsTable.append("set_name text NOT NULL,");
createReferenceSetsTable.append("version text NOT NULL,");
createReferenceSetsTable.append("known_status integer NOT NULL,");
createReferenceSetsTable.append("read_only boolean NOT NULL,");
createReferenceSetsTable.append("type integer NOT NULL,");
createReferenceSetsTable.append("import_date text NOT NULL,");
createReferenceSetsTable.append("foreign key (org_id) references organizations(id) ON UPDATE SET NULL ON DELETE SET NULL,");
createReferenceSetsTable.append("CONSTRAINT hash_set_unique UNIQUE (set_name, version)");
createReferenceSetsTable.append(")");
String referenceSetsIdx1 = "CREATE INDEX IF NOT EXISTS reference_sets_org_id ON reference_sets (org_id)";
// Each "%s" will be replaced with the relevant reference_TYPE table name.
StringBuilder createReferenceTypesTableTemplate = new StringBuilder();
createReferenceTypesTableTemplate.append("CREATE TABLE IF NOT EXISTS %s (");
createReferenceTypesTableTemplate.append("id integer primary key autoincrement NOT NULL,");
createReferenceTypesTableTemplate.append("reference_set_id integer,");
createReferenceTypesTableTemplate.append("value text NOT NULL,");
createReferenceTypesTableTemplate.append("known_status integer NOT NULL,");
createReferenceTypesTableTemplate.append("comment text,");
createReferenceTypesTableTemplate.append("CONSTRAINT %s_multi_unique UNIQUE(reference_set_id, value) ON CONFLICT IGNORE,");
createReferenceTypesTableTemplate.append("foreign key (reference_set_id) references reference_sets(id) ON UPDATE SET NULL ON DELETE SET NULL");
createReferenceTypesTableTemplate.append(")");
// Each "%s" will be replaced with the relevant reference_TYPE table name.
String referenceTypesIdx1 = "CREATE INDEX IF NOT EXISTS %s_value ON %s (value)";
String referenceTypesIdx2 = "CREATE INDEX IF NOT EXISTS %s_value_known_status ON %s (value, known_status)";
StringBuilder createCorrelationTypesTable = new StringBuilder();
createCorrelationTypesTable.append("CREATE TABLE IF NOT EXISTS correlation_types (");
createCorrelationTypesTable.append("id integer primary key autoincrement NOT NULL,");
createCorrelationTypesTable.append("display_name text NOT NULL,");
createCorrelationTypesTable.append("db_table_name text NOT NULL,");
createCorrelationTypesTable.append("supported integer NOT NULL,");
createCorrelationTypesTable.append("enabled integer NOT NULL,");
createCorrelationTypesTable.append("CONSTRAINT correlation_types_names UNIQUE (display_name, db_table_name)");
createCorrelationTypesTable.append(")");
String createArtifactInstancesTableTemplate = getCreateArtifactInstancesTableTemplate();
String instancesCaseIdIdx = getAddCaseIdIndexTemplate();
String instancesDatasourceIdIdx = getAddDataSourceIdIndexTemplate();
String instancesValueIdx = getAddValueIndexTemplate();
String instancesKnownStatusIdx = getAddKnownStatusIndexTemplate();
String instancesObjectIdIdx = getAddObjectIdIndexTemplate();
// NOTE: the db_info table currenly only has 1 row, so having an index
// provides no benefit.
Connection conn = null;
try {
conn = rdbmsCentralRepo.getEphemeralConnection();
if (null == conn) {
return false;
}
Statement stmt = conn.createStatement();
stmt.execute(PRAGMA_JOURNAL_WAL);
stmt.execute(PRAGMA_SYNC_OFF);
stmt.execute(PRAGMA_READ_UNCOMMITTED_TRUE);
stmt.execute(PRAGMA_ENCODING_UTF8);
stmt.execute(PRAGMA_PAGE_SIZE_4096);
stmt.execute(PRAGMA_FOREIGN_KEYS_ON);
stmt.execute(createOrganizationsTable.toString());
stmt.execute(createCasesTable.toString());
stmt.execute(casesIdx1);
stmt.execute(casesIdx2);
stmt.execute(getCreateDataSourcesTableStatement());
stmt.execute(getAddDataSourcesNameIndexStatement());
stmt.execute(getAddDataSourcesObjectIdIndexStatement());
stmt.execute(createReferenceSetsTable.toString());
stmt.execute(referenceSetsIdx1);
stmt.execute(createCorrelationTypesTable.toString());
/*
* Note that the essentially useless id column in the following
* table is required for backwards compatibility. Otherwise, the
* name column could be the primary key.
*/
stmt.execute("CREATE TABLE db_info (id INTEGER PRIMARY KEY, name TEXT UNIQUE NOT NULL, value TEXT NOT NULL)");
stmt.execute("INSERT INTO db_info (name, value) VALUES ('" + RdbmsCentralRepo.SCHEMA_MAJOR_VERSION_KEY + "', '" + SOFTWARE_CR_DB_SCHEMA_VERSION.getMajor() + "')");
stmt.execute("INSERT INTO db_info (name, value) VALUES ('" + RdbmsCentralRepo.SCHEMA_MINOR_VERSION_KEY + "', '" + SOFTWARE_CR_DB_SCHEMA_VERSION.getMinor() + "')");
stmt.execute("INSERT INTO db_info (name, value) VALUES ('" + RdbmsCentralRepo.CREATION_SCHEMA_MAJOR_VERSION_KEY + "', '" + SOFTWARE_CR_DB_SCHEMA_VERSION.getMajor() + "')");
stmt.execute("INSERT INTO db_info (name, value) VALUES ('" + RdbmsCentralRepo.CREATION_SCHEMA_MINOR_VERSION_KEY + "', '" + SOFTWARE_CR_DB_SCHEMA_VERSION.getMinor() + "')");
// Create a separate instance and reference table for each artifact type
List<CorrelationAttributeInstance.Type> DEFAULT_CORRELATION_TYPES = CorrelationAttributeInstance.getDefaultCorrelationTypes();
String reference_type_dbname;
String instance_type_dbname;
for (CorrelationAttributeInstance.Type type : DEFAULT_CORRELATION_TYPES) {
reference_type_dbname = CentralRepoDbUtil.correlationTypeToReferenceTableName(type);
instance_type_dbname = CentralRepoDbUtil.correlationTypeToInstanceTableName(type);
stmt.execute(String.format(createArtifactInstancesTableTemplate, instance_type_dbname, instance_type_dbname));
stmt.execute(String.format(instancesCaseIdIdx, instance_type_dbname, instance_type_dbname));
stmt.execute(String.format(instancesDatasourceIdIdx, instance_type_dbname, instance_type_dbname));
stmt.execute(String.format(instancesValueIdx, instance_type_dbname, instance_type_dbname));
stmt.execute(String.format(instancesKnownStatusIdx, instance_type_dbname, instance_type_dbname));
stmt.execute(String.format(instancesObjectIdIdx, instance_type_dbname, instance_type_dbname));
// FUTURE: allow more than the FILES type
if (type.getId() == CorrelationAttributeInstance.FILES_TYPE_ID) {
stmt.execute(String.format(createReferenceTypesTableTemplate.toString(), reference_type_dbname, reference_type_dbname));
stmt.execute(String.format(referenceTypesIdx1, reference_type_dbname, reference_type_dbname));
stmt.execute(String.format(referenceTypesIdx2, reference_type_dbname, reference_type_dbname));
}
}
} catch (SQLException ex) {
LOGGER.log(Level.SEVERE, "Error initializing db schema.", ex); // NON-NLS
return false;
} catch (CentralRepoException ex) {
LOGGER.log(Level.SEVERE, "Error getting default correlation types. Likely due to one or more Type's with an invalid db table name."); // NON-NLS
return false;
} finally {
CentralRepoDbUtil.closeConnection(conn);
}
return true;
}
/**
* Get the template String for creating a new _instances table in a
* Sqlite central repository. %s will exist in the template where the
* name of the new table will be addedd.
*
* @return a String which is a template for cretating a new _instances
* table
*/
static String getCreateArtifactInstancesTableTemplate() {
// Each "%s" will be replaced with the relevant TYPE_instances table name.
return "CREATE TABLE IF NOT EXISTS %s (id integer primary key autoincrement NOT NULL,"
+ "case_id integer NOT NULL,data_source_id integer NOT NULL,value text NOT NULL,"
+ "file_path text NOT NULL,known_status integer NOT NULL,comment text,file_obj_id integer,"
+ "CONSTRAINT %s_multi_unique UNIQUE(data_source_id, value, file_path) ON CONFLICT IGNORE,"
+ "foreign key (case_id) references cases(id) ON UPDATE SET NULL ON DELETE SET NULL,"
+ "foreign key (data_source_id) references data_sources(id) ON UPDATE SET NULL ON DELETE SET NULL)";
}
/**
* Get the template for creating an index on the case_id column of an
* instance table. %s will exist in the template where the name of the
* new table will be addedd.
*
* @return a String which is a template for adding an index to the
* case_id column of a _instances table
*/
static String getAddCaseIdIndexTemplate() {
// Each "%s" will be replaced with the relevant TYPE_instances table name.
return "CREATE INDEX IF NOT EXISTS %s_case_id ON %s (case_id)";
}
/**
* Get the template for creating an index on the data_source_id column
* of an instance table. %s will exist in the template where the name of
* the new table will be addedd.
*
* @return a String which is a template for adding an index to the
* data_source_id column of a _instances table
*/
static String getAddDataSourceIdIndexTemplate() {
// Each "%s" will be replaced with the relevant TYPE_instances table name.
return "CREATE INDEX IF NOT EXISTS %s_data_source_id ON %s (data_source_id)";
}
/**
* Get the template for creating an index on the value column of an
* instance table. %s will exist in the template where the name of the
* new table will be addedd.
*
* @return a String which is a template for adding an index to the value
* column of a _instances table
*/
static String getAddValueIndexTemplate() {
// Each "%s" will be replaced with the relevant TYPE_instances table name.
return "CREATE INDEX IF NOT EXISTS %s_value ON %s (value)";
}
/**
* Get the template for creating an index on the known_status column of
* an instance table. %s will exist in the template where the name of
* the new table will be addedd.
*
* @return a String which is a template for adding an index to the
* known_status column of a _instances table
*/
static String getAddKnownStatusIndexTemplate() {
// Each "%s" will be replaced with the relevant TYPE_instances table name.
return "CREATE INDEX IF NOT EXISTS %s_value_known_status ON %s (value, known_status)";
}
/**
* Get the template for creating an index on the file_obj_id column of
* an instance table. %s will exist in the template where the name of
* the new table will be addedd.
*
* @return a String which is a template for adding an index to the
* file_obj_id column of a _instances table
*/
static String getAddObjectIdIndexTemplate() {
// Each "%s" will be replaced with the relevant TYPE_instances table name.
return "CREATE INDEX IF NOT EXISTS %s_file_obj_id ON %s (file_obj_id)";
}
/**
* Get the statement String for creating a new data_sources table in a
* Sqlite central repository.
*
* @return a String which is a statement for cretating a new
* data_sources table
*/
static String getCreateDataSourcesTableStatement() {
return "CREATE TABLE IF NOT EXISTS data_sources (id integer primary key autoincrement NOT NULL,"
+ "case_id integer NOT NULL,device_id text NOT NULL,name text NOT NULL,datasource_obj_id integer,"
+ "md5 text DEFAULT NULL,sha1 text DEFAULT NULL,sha256 text DEFAULT NULL,"
+ "foreign key (case_id) references cases(id) ON UPDATE SET NULL ON DELETE SET NULL,"
+ "CONSTRAINT datasource_unique UNIQUE (case_id, datasource_obj_id))";
}
/**
* Get the statement for creating an index on the name column of the
* data_sources table.
*
* @return a String which is a statement for adding an index on the name
* column of the data_sources table.
*/
static String getAddDataSourcesNameIndexStatement() {
return "CREATE INDEX IF NOT EXISTS data_sources_name ON data_sources (name)";
}
/**
* Get the statement for creating an index on the data_sources_object_id
* column of the data_sources table.
*
* @return a String which is a statement for adding an index on the
* data_sources_object_id column of the data_sources table.
*/
static String getAddDataSourcesObjectIdIndexStatement() {
return "CREATE INDEX IF NOT EXISTS data_sources_object_id ON data_sources (datasource_obj_id)";
}
}
// TBD RAMAN - temporary container to store all Pstgres methods, till we unify...
public static class PostgresCRSchemaCreator {
/**
* Initialize the database schema.
*
* Requires valid connectionPool.
*
* This method is called from within connect(), so we cannot call
* connect() to get a connection. This method is called after
* setupConnectionPool(), so it is safe to assume that a valid
* connectionPool exists. The implementation of connect() is
* synchronized, so we can safely use the connectionPool object
* directly.
*/
public static boolean initializeDatabaseSchema(RdbmsCentralRepo rdbmsCentralRepo) {
// The "id" column is an alias for the built-in 64-bit int "rowid" column.
// It is autoincrementing by default and must be of type "integer primary key".
// We've omitted the autoincrement argument because we are not currently
// using the id value to search for specific rows, so we do not care
// if a rowid is re-used after an existing rows was previously deleted.
StringBuilder createOrganizationsTable = new StringBuilder();
createOrganizationsTable.append("CREATE TABLE IF NOT EXISTS organizations (");
createOrganizationsTable.append("id SERIAL PRIMARY KEY,");
createOrganizationsTable.append("org_name text NOT NULL,");
createOrganizationsTable.append("poc_name text NOT NULL,");
createOrganizationsTable.append("poc_email text NOT NULL,");
createOrganizationsTable.append("poc_phone text NOT NULL,");
createOrganizationsTable.append("CONSTRAINT org_name_unique UNIQUE (org_name)");
createOrganizationsTable.append(")");
// NOTE: The organizations will only have a small number of rows, so
// an index is probably not worthwhile.
StringBuilder createCasesTable = new StringBuilder();
createCasesTable.append("CREATE TABLE IF NOT EXISTS cases (");
createCasesTable.append("id SERIAL PRIMARY KEY,");
createCasesTable.append("case_uid text NOT NULL,");
createCasesTable.append("org_id integer,");
createCasesTable.append("case_name text NOT NULL,");
createCasesTable.append("creation_date text NOT NULL,");
createCasesTable.append("case_number text,");
createCasesTable.append("examiner_name text,");
createCasesTable.append("examiner_email text,");
createCasesTable.append("examiner_phone text,");
createCasesTable.append("notes text,");
createCasesTable.append("foreign key (org_id) references organizations(id) ON UPDATE SET NULL ON DELETE SET NULL,");
createCasesTable.append("CONSTRAINT case_uid_unique UNIQUE (case_uid)");
createCasesTable.append(")");
// NOTE: when there are few cases in the cases table, these indices may not be worthwhile
String casesIdx1 = "CREATE INDEX IF NOT EXISTS cases_org_id ON cases (org_id)";
String casesIdx2 = "CREATE INDEX IF NOT EXISTS cases_case_uid ON cases (case_uid)";
StringBuilder createReferenceSetsTable = new StringBuilder();
createReferenceSetsTable.append("CREATE TABLE IF NOT EXISTS reference_sets (");
createReferenceSetsTable.append("id SERIAL PRIMARY KEY,");
createReferenceSetsTable.append("org_id integer NOT NULL,");
createReferenceSetsTable.append("set_name text NOT NULL,");
createReferenceSetsTable.append("version text NOT NULL,");
createReferenceSetsTable.append("known_status integer NOT NULL,");
createReferenceSetsTable.append("read_only boolean NOT NULL,");
createReferenceSetsTable.append("type integer NOT NULL,");
createReferenceSetsTable.append("import_date text NOT NULL,");
createReferenceSetsTable.append("foreign key (org_id) references organizations(id) ON UPDATE SET NULL ON DELETE SET NULL,");
createReferenceSetsTable.append("CONSTRAINT hash_set_unique UNIQUE (set_name, version)");
createReferenceSetsTable.append(")");
String referenceSetsIdx1 = "CREATE INDEX IF NOT EXISTS reference_sets_org_id ON reference_sets (org_id)";
// Each "%s" will be replaced with the relevant reference_TYPE table name.
StringBuilder createReferenceTypesTableTemplate = new StringBuilder();
createReferenceTypesTableTemplate.append("CREATE TABLE IF NOT EXISTS %s (");
createReferenceTypesTableTemplate.append("id SERIAL PRIMARY KEY,");
createReferenceTypesTableTemplate.append("reference_set_id integer,");
createReferenceTypesTableTemplate.append("value text NOT NULL,");
createReferenceTypesTableTemplate.append("known_status integer NOT NULL,");
createReferenceTypesTableTemplate.append("comment text,");
createReferenceTypesTableTemplate.append("CONSTRAINT %s_multi_unique UNIQUE (reference_set_id, value),");
createReferenceTypesTableTemplate.append("foreign key (reference_set_id) references reference_sets(id) ON UPDATE SET NULL ON DELETE SET NULL");
createReferenceTypesTableTemplate.append(")");
// Each "%s" will be replaced with the relevant reference_TYPE table name.
String referenceTypesIdx1 = "CREATE INDEX IF NOT EXISTS %s_value ON %s (value)";
String referenceTypesIdx2 = "CREATE INDEX IF NOT EXISTS %s_value_known_status ON %s (value, known_status)";
StringBuilder createCorrelationTypesTable = new StringBuilder();
createCorrelationTypesTable.append("CREATE TABLE IF NOT EXISTS correlation_types (");
createCorrelationTypesTable.append("id SERIAL PRIMARY KEY,");
createCorrelationTypesTable.append("display_name text NOT NULL,");
createCorrelationTypesTable.append("db_table_name text NOT NULL,");
createCorrelationTypesTable.append("supported integer NOT NULL,");
createCorrelationTypesTable.append("enabled integer NOT NULL,");
createCorrelationTypesTable.append("CONSTRAINT correlation_types_names UNIQUE (display_name, db_table_name)");
createCorrelationTypesTable.append(")");
String createArtifactInstancesTableTemplate = getCreateArtifactInstancesTableTemplate();
String instancesCaseIdIdx = getAddCaseIdIndexTemplate();
String instancesDatasourceIdIdx = getAddDataSourceIdIndexTemplate();
String instancesValueIdx = getAddValueIndexTemplate();
String instancesKnownStatusIdx = getAddKnownStatusIndexTemplate();
String instancesObjectIdIdx = getAddObjectIdIndexTemplate();
// NOTE: the db_info table currenly only has 1 row, so having an index
// provides no benefit.
Connection conn = null;
try {
conn = rdbmsCentralRepo.getEphemeralConnection();
if (null == conn) {
return false;
}
Statement stmt = conn.createStatement();
stmt.execute(createOrganizationsTable.toString());
stmt.execute(createCasesTable.toString());
stmt.execute(casesIdx1);
stmt.execute(casesIdx2);
stmt.execute(getCreateDataSourcesTableStatement());
stmt.execute(getAddDataSourcesNameIndexStatement());
stmt.execute(getAddDataSourcesObjectIdIndexStatement());
stmt.execute(createReferenceSetsTable.toString());
stmt.execute(referenceSetsIdx1);
stmt.execute(createCorrelationTypesTable.toString());
/*
* Note that the essentially useless id column in the following
* table is required for backwards compatibility. Otherwise, the
* name column could be the primary key.
*/
stmt.execute("CREATE TABLE db_info (id SERIAL, name TEXT UNIQUE NOT NULL, value TEXT NOT NULL)");
stmt.execute("INSERT INTO db_info (name, value) VALUES ('" + RdbmsCentralRepo.SCHEMA_MAJOR_VERSION_KEY + "', '" + SOFTWARE_CR_DB_SCHEMA_VERSION.getMajor() + "')");
stmt.execute("INSERT INTO db_info (name, value) VALUES ('" + RdbmsCentralRepo.SCHEMA_MINOR_VERSION_KEY + "', '" + SOFTWARE_CR_DB_SCHEMA_VERSION.getMinor() + "')");
stmt.execute("INSERT INTO db_info (name, value) VALUES ('" + RdbmsCentralRepo.CREATION_SCHEMA_MAJOR_VERSION_KEY + "', '" + SOFTWARE_CR_DB_SCHEMA_VERSION.getMajor() + "')");
stmt.execute("INSERT INTO db_info (name, value) VALUES ('" + RdbmsCentralRepo.CREATION_SCHEMA_MINOR_VERSION_KEY + "', '" + SOFTWARE_CR_DB_SCHEMA_VERSION.getMinor() + "')");
// Create a separate instance and reference table for each correlation type
List<CorrelationAttributeInstance.Type> DEFAULT_CORRELATION_TYPES = CorrelationAttributeInstance.getDefaultCorrelationTypes();
String reference_type_dbname;
String instance_type_dbname;
for (CorrelationAttributeInstance.Type type : DEFAULT_CORRELATION_TYPES) {
reference_type_dbname = CentralRepoDbUtil.correlationTypeToReferenceTableName(type);
instance_type_dbname = CentralRepoDbUtil.correlationTypeToInstanceTableName(type);
stmt.execute(String.format(createArtifactInstancesTableTemplate, instance_type_dbname, instance_type_dbname));
stmt.execute(String.format(instancesCaseIdIdx, instance_type_dbname, instance_type_dbname));
stmt.execute(String.format(instancesDatasourceIdIdx, instance_type_dbname, instance_type_dbname));
stmt.execute(String.format(instancesValueIdx, instance_type_dbname, instance_type_dbname));
stmt.execute(String.format(instancesKnownStatusIdx, instance_type_dbname, instance_type_dbname));
stmt.execute(String.format(instancesObjectIdIdx, instance_type_dbname, instance_type_dbname));
// FUTURE: allow more than the FILES type
if (type.getId() == CorrelationAttributeInstance.FILES_TYPE_ID) {
stmt.execute(String.format(createReferenceTypesTableTemplate.toString(), reference_type_dbname, reference_type_dbname));
stmt.execute(String.format(referenceTypesIdx1, reference_type_dbname, reference_type_dbname));
stmt.execute(String.format(referenceTypesIdx2, reference_type_dbname, reference_type_dbname));
}
}
} catch (SQLException ex) {
LOGGER.log(Level.SEVERE, "Error initializing db schema.", ex); // NON-NLS
return false;
} catch (CentralRepoException ex) {
LOGGER.log(Level.SEVERE, "Error getting default correlation types. Likely due to one or more Type's with an invalid db table name."); // NON-NLS
return false;
} finally {
CentralRepoDbUtil.closeConnection(conn);
}
return true;
}
/**
* Get the template String for creating a new _instances table in a
* Postgres central repository. %s will exist in the template where the
* name of the new table will be addedd.
*
* @return a String which is a template for cretating a new _instances
* table
*/
static String getCreateArtifactInstancesTableTemplate() {
// Each "%s" will be replaced with the relevant TYPE_instances table name.
return ("CREATE TABLE IF NOT EXISTS %s (id SERIAL PRIMARY KEY,case_id integer NOT NULL,"
+ "data_source_id integer NOT NULL,value text NOT NULL,file_path text NOT NULL,"
+ "known_status integer NOT NULL,comment text,file_obj_id BIGINT,"
+ "CONSTRAINT %s_multi_unique_ UNIQUE (data_source_id, value, file_path),"
+ "foreign key (case_id) references cases(id) ON UPDATE SET NULL ON DELETE SET NULL,"
+ "foreign key (data_source_id) references data_sources(id) ON UPDATE SET NULL ON DELETE SET NULL)");
}
/**
* Get the template for creating an index on the case_id column of an
* instance table. %s will exist in the template where the name of the
* new table will be addedd.
*
* @return a String which is a template for adding an index to the
* case_id column of a _instances table
*/
static String getAddCaseIdIndexTemplate() {
// Each "%s" will be replaced with the relevant TYPE_instances table name.
return "CREATE INDEX IF NOT EXISTS %s_case_id ON %s (case_id)";
}
/**
* Get the template for creating an index on the data_source_id column
* of an instance table. %s will exist in the template where the name of
* the new table will be addedd.
*
* @return a String which is a template for adding an index to the
* data_source_id column of a _instances table
*/
static String getAddDataSourceIdIndexTemplate() {
// Each "%s" will be replaced with the relevant TYPE_instances table name.
return "CREATE INDEX IF NOT EXISTS %s_data_source_id ON %s (data_source_id)";
}
/**
* Get the template for creating an index on the value column of an
* instance table. %s will exist in the template where the name of the
* new table will be addedd.
*
* @return a String which is a template for adding an index to the value
* column of a _instances table
*/
static String getAddValueIndexTemplate() {
// Each "%s" will be replaced with the relevant TYPE_instances table name.
return "CREATE INDEX IF NOT EXISTS %s_value ON %s (value)";
}
/**
* Get the template for creating an index on the known_status column of
* an instance table. %s will exist in the template where the name of
* the new table will be addedd.
*
* @return a String which is a template for adding an index to the
* known_status column of a _instances table
*/
static String getAddKnownStatusIndexTemplate() {
// Each "%s" will be replaced with the relevant TYPE_instances table name.
return "CREATE INDEX IF NOT EXISTS %s_value_known_status ON %s (value, known_status)";
}
/**
* Get the template for creating an index on the file_obj_id column of
* an instance table. %s will exist in the template where the name of
* the new table will be addedd.
*
* @return a String which is a template for adding an index to the
* file_obj_id column of a _instances table
*/
static String getAddObjectIdIndexTemplate() {
// Each "%s" will be replaced with the relevant TYPE_instances table name.
return "CREATE INDEX IF NOT EXISTS %s_file_obj_id ON %s (file_obj_id)";
}
/**
* Get the statement String for creating a new data_sources table in a
* Postgres central repository.
*
* @return a String which is a statement for cretating a new
* data_sources table
*/
static String getCreateDataSourcesTableStatement() {
return "CREATE TABLE IF NOT EXISTS data_sources "
+ "(id SERIAL PRIMARY KEY,case_id integer NOT NULL,device_id text NOT NULL,"
+ "name text NOT NULL,datasource_obj_id BIGINT,md5 text DEFAULT NULL,"
+ "sha1 text DEFAULT NULL,sha256 text DEFAULT NULL,"
+ "foreign key (case_id) references cases(id) ON UPDATE SET NULL ON DELETE SET NULL,"
+ "CONSTRAINT datasource_unique UNIQUE (case_id, datasource_obj_id))";
}
/**
* Get the statement for creating an index on the name column of the
* data_sources table.
*
* @return a String which is a statement for adding an index on the name
* column of the data_sources table.
*/
static String getAddDataSourcesNameIndexStatement() {
return "CREATE INDEX IF NOT EXISTS data_sources_name ON data_sources (name)";
}
/**
* Get the statement for creating an index on the data_sources_object_id
* column of the data_sources table.
*
* @return a String which is a statement for adding an index on the
* data_sources_object_id column of the data_sources table.
*/
static String getAddDataSourcesObjectIdIndexStatement() {
return "CREATE INDEX IF NOT EXISTS data_sources_object_id ON data_sources (datasource_obj_id)";
}
}
public boolean insertDefaultDatabaseContent() {
Connection conn = rdbmsCentralRepo.getEphemeralConnection();
if (null == conn) {
return false;
}
boolean result = CentralRepoDbUtil.insertDefaultCorrelationTypes(conn) && CentralRepoDbUtil.insertDefaultOrganization(conn);
CentralRepoDbUtil.closeConnection(conn);
return result;
}
}

View File

@ -113,6 +113,7 @@ final class SqliteCentralRepo extends RdbmsCentralRepo {
@Override @Override
public void reset() throws CentralRepoException { public void reset() throws CentralRepoException {
try { try {
// RAMAN TBD: this should be moved to RdbmsCentralRepoSchemaFactory ??
acquireExclusiveLock(); acquireExclusiveLock();
Connection conn = connect(); Connection conn = connect();
@ -144,7 +145,9 @@ final class SqliteCentralRepo extends RdbmsCentralRepo {
CentralRepoDbUtil.closeConnection(conn); CentralRepoDbUtil.closeConnection(conn);
} }
dbSettings.insertDefaultDatabaseContent(); //RdbmsCentralRepoSchemaFactory.getInstance().insertDefaultDatabaseContent();
RdbmsCentralRepoSchemaFactory centralRepoSchemaFactory = new RdbmsCentralRepoSchemaFactory(CentralRepoPlatforms.SQLITE);
centralRepoSchemaFactory.insertDefaultDatabaseContent();
} finally { } finally {
releaseExclusiveLock(); releaseExclusiveLock();
} }
@ -226,6 +229,10 @@ final class SqliteCentralRepo extends RdbmsCentralRepo {
return ""; return "";
} }
@Override
protected Connection getEphemeralConnection() {
return this.dbSettings.getEphemeralConnection();
}
/** /**
* Add a new name/value pair in the db_info table. * Add a new name/value pair in the db_info table.
* *

View File

@ -25,14 +25,11 @@ import java.nio.file.InvalidPathException;
import java.sql.Connection; import java.sql.Connection;
import java.sql.DriverManager; import java.sql.DriverManager;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.ModuleSettings; import org.sleuthkit.autopsy.coreutils.ModuleSettings;
import org.sleuthkit.autopsy.coreutils.PlatformUtil; import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import static org.sleuthkit.autopsy.centralrepository.datamodel.RdbmsCentralRepo.SOFTWARE_CR_DB_SCHEMA_VERSION;
/** /**
* Settings for the sqlite implementation of the Central Repository database * Settings for the sqlite implementation of the Central Repository database
@ -48,13 +45,7 @@ public final class SqliteCentralRepoSettings {
private final static String JDBC_DRIVER = "org.sqlite.JDBC"; // NON-NLS private final static String JDBC_DRIVER = "org.sqlite.JDBC"; // NON-NLS
private final static String JDBC_BASE_URI = "jdbc:sqlite:"; // NON-NLS private final static String JDBC_BASE_URI = "jdbc:sqlite:"; // NON-NLS
private final static String VALIDATION_QUERY = "SELECT count(*) from sqlite_master"; // NON-NLS private final static String VALIDATION_QUERY = "SELECT count(*) from sqlite_master"; // NON-NLS
private final static String PRAGMA_SYNC_OFF = "PRAGMA synchronous = OFF";
private final static String PRAGMA_SYNC_NORMAL = "PRAGMA synchronous = NORMAL";
private final static String PRAGMA_JOURNAL_WAL = "PRAGMA journal_mode = WAL";
private final static String PRAGMA_READ_UNCOMMITTED_TRUE = "PRAGMA read_uncommitted = True";
private final static String PRAGMA_ENCODING_UTF8 = "PRAGMA encoding = 'UTF-8'";
private final static String PRAGMA_PAGE_SIZE_4096 = "PRAGMA page_size = 4096";
private final static String PRAGMA_FOREIGN_KEYS_ON = "PRAGMA foreign_keys = ON";
private final static String DB_NAMES_REGEX = "[a-z][a-z0-9_]*(\\.db)?"; private final static String DB_NAMES_REGEX = "[a-z][a-z0-9_]*(\\.db)?";
private String dbName; private String dbName;
private String dbDirectory; private String dbDirectory;
@ -182,7 +173,7 @@ public final class SqliteCentralRepoSettings {
* *
* @return Connection or null. * @return Connection or null.
*/ */
private Connection getEphemeralConnection() { Connection getEphemeralConnection() {
if (!dbDirectoryExists()) { if (!dbDirectoryExists()) {
return null; return null;
} }
@ -233,312 +224,6 @@ public final class SqliteCentralRepoSettings {
return result; return result;
} }
/**
* Initialize the database schema.
*
* Requires valid connectionPool.
*
* This method is called from within connect(), so we cannot call connect()
* to get a connection. This method is called after setupConnectionPool(),
* so it is safe to assume that a valid connectionPool exists. The
* implementation of connect() is synchronized, so we can safely use the
* connectionPool object directly.
*/
public boolean initializeDatabaseSchema() {
// The "id" column is an alias for the built-in 64-bit int "rowid" column.
// It is autoincrementing by default and must be of type "integer primary key".
// We've omitted the autoincrement argument because we are not currently
// using the id value to search for specific rows, so we do not care
// if a rowid is re-used after an existing rows was previously deleted.
StringBuilder createOrganizationsTable = new StringBuilder();
createOrganizationsTable.append("CREATE TABLE IF NOT EXISTS organizations (");
createOrganizationsTable.append("id integer primary key autoincrement NOT NULL,");
createOrganizationsTable.append("org_name text NOT NULL,");
createOrganizationsTable.append("poc_name text NOT NULL,");
createOrganizationsTable.append("poc_email text NOT NULL,");
createOrganizationsTable.append("poc_phone text NOT NULL,");
createOrganizationsTable.append("CONSTRAINT org_name_unique UNIQUE (org_name)");
createOrganizationsTable.append(")");
// NOTE: The organizations will only have a small number of rows, so
// an index is probably not worthwhile.
StringBuilder createCasesTable = new StringBuilder();
createCasesTable.append("CREATE TABLE IF NOT EXISTS cases (");
createCasesTable.append("id integer primary key autoincrement NOT NULL,");
createCasesTable.append("case_uid text NOT NULL,");
createCasesTable.append("org_id integer,");
createCasesTable.append("case_name text NOT NULL,");
createCasesTable.append("creation_date text NOT NULL,");
createCasesTable.append("case_number text,");
createCasesTable.append("examiner_name text,");
createCasesTable.append("examiner_email text,");
createCasesTable.append("examiner_phone text,");
createCasesTable.append("notes text,");
createCasesTable.append("CONSTRAINT case_uid_unique UNIQUE(case_uid) ON CONFLICT IGNORE,");
createCasesTable.append("foreign key (org_id) references organizations(id) ON UPDATE SET NULL ON DELETE SET NULL");
createCasesTable.append(")");
// NOTE: when there are few cases in the cases table, these indices may not be worthwhile
String casesIdx1 = "CREATE INDEX IF NOT EXISTS cases_org_id ON cases (org_id)";
String casesIdx2 = "CREATE INDEX IF NOT EXISTS cases_case_uid ON cases (case_uid)";
StringBuilder createReferenceSetsTable = new StringBuilder();
createReferenceSetsTable.append("CREATE TABLE IF NOT EXISTS reference_sets (");
createReferenceSetsTable.append("id integer primary key autoincrement NOT NULL,");
createReferenceSetsTable.append("org_id integer NOT NULL,");
createReferenceSetsTable.append("set_name text NOT NULL,");
createReferenceSetsTable.append("version text NOT NULL,");
createReferenceSetsTable.append("known_status integer NOT NULL,");
createReferenceSetsTable.append("read_only boolean NOT NULL,");
createReferenceSetsTable.append("type integer NOT NULL,");
createReferenceSetsTable.append("import_date text NOT NULL,");
createReferenceSetsTable.append("foreign key (org_id) references organizations(id) ON UPDATE SET NULL ON DELETE SET NULL,");
createReferenceSetsTable.append("CONSTRAINT hash_set_unique UNIQUE (set_name, version)");
createReferenceSetsTable.append(")");
String referenceSetsIdx1 = "CREATE INDEX IF NOT EXISTS reference_sets_org_id ON reference_sets (org_id)";
// Each "%s" will be replaced with the relevant reference_TYPE table name.
StringBuilder createReferenceTypesTableTemplate = new StringBuilder();
createReferenceTypesTableTemplate.append("CREATE TABLE IF NOT EXISTS %s (");
createReferenceTypesTableTemplate.append("id integer primary key autoincrement NOT NULL,");
createReferenceTypesTableTemplate.append("reference_set_id integer,");
createReferenceTypesTableTemplate.append("value text NOT NULL,");
createReferenceTypesTableTemplate.append("known_status integer NOT NULL,");
createReferenceTypesTableTemplate.append("comment text,");
createReferenceTypesTableTemplate.append("CONSTRAINT %s_multi_unique UNIQUE(reference_set_id, value) ON CONFLICT IGNORE,");
createReferenceTypesTableTemplate.append("foreign key (reference_set_id) references reference_sets(id) ON UPDATE SET NULL ON DELETE SET NULL");
createReferenceTypesTableTemplate.append(")");
// Each "%s" will be replaced with the relevant reference_TYPE table name.
String referenceTypesIdx1 = "CREATE INDEX IF NOT EXISTS %s_value ON %s (value)";
String referenceTypesIdx2 = "CREATE INDEX IF NOT EXISTS %s_value_known_status ON %s (value, known_status)";
StringBuilder createCorrelationTypesTable = new StringBuilder();
createCorrelationTypesTable.append("CREATE TABLE IF NOT EXISTS correlation_types (");
createCorrelationTypesTable.append("id integer primary key autoincrement NOT NULL,");
createCorrelationTypesTable.append("display_name text NOT NULL,");
createCorrelationTypesTable.append("db_table_name text NOT NULL,");
createCorrelationTypesTable.append("supported integer NOT NULL,");
createCorrelationTypesTable.append("enabled integer NOT NULL,");
createCorrelationTypesTable.append("CONSTRAINT correlation_types_names UNIQUE (display_name, db_table_name)");
createCorrelationTypesTable.append(")");
String createArtifactInstancesTableTemplate = getCreateArtifactInstancesTableTemplate();
String instancesCaseIdIdx = getAddCaseIdIndexTemplate();
String instancesDatasourceIdIdx = getAddDataSourceIdIndexTemplate();
String instancesValueIdx = getAddValueIndexTemplate();
String instancesKnownStatusIdx = getAddKnownStatusIndexTemplate();
String instancesObjectIdIdx = getAddObjectIdIndexTemplate();
// NOTE: the db_info table currenly only has 1 row, so having an index
// provides no benefit.
Connection conn = null;
try {
conn = getEphemeralConnection();
if (null == conn) {
return false;
}
Statement stmt = conn.createStatement();
stmt.execute(PRAGMA_JOURNAL_WAL);
stmt.execute(PRAGMA_SYNC_OFF);
stmt.execute(PRAGMA_READ_UNCOMMITTED_TRUE);
stmt.execute(PRAGMA_ENCODING_UTF8);
stmt.execute(PRAGMA_PAGE_SIZE_4096);
stmt.execute(PRAGMA_FOREIGN_KEYS_ON);
stmt.execute(createOrganizationsTable.toString());
stmt.execute(createCasesTable.toString());
stmt.execute(casesIdx1);
stmt.execute(casesIdx2);
stmt.execute(getCreateDataSourcesTableStatement());
stmt.execute(getAddDataSourcesNameIndexStatement());
stmt.execute(getAddDataSourcesObjectIdIndexStatement());
stmt.execute(createReferenceSetsTable.toString());
stmt.execute(referenceSetsIdx1);
stmt.execute(createCorrelationTypesTable.toString());
/*
* Note that the essentially useless id column in the following
* table is required for backwards compatibility. Otherwise, the
* name column could be the primary key.
*/
stmt.execute("CREATE TABLE db_info (id INTEGER PRIMARY KEY, name TEXT UNIQUE NOT NULL, value TEXT NOT NULL)");
stmt.execute("INSERT INTO db_info (name, value) VALUES ('" + RdbmsCentralRepo.SCHEMA_MAJOR_VERSION_KEY + "', '" + SOFTWARE_CR_DB_SCHEMA_VERSION.getMajor() + "')");
stmt.execute("INSERT INTO db_info (name, value) VALUES ('" + RdbmsCentralRepo.SCHEMA_MINOR_VERSION_KEY + "', '" + SOFTWARE_CR_DB_SCHEMA_VERSION.getMinor() + "')");
stmt.execute("INSERT INTO db_info (name, value) VALUES ('" + RdbmsCentralRepo.CREATION_SCHEMA_MAJOR_VERSION_KEY + "', '" + SOFTWARE_CR_DB_SCHEMA_VERSION.getMajor() + "')");
stmt.execute("INSERT INTO db_info (name, value) VALUES ('" + RdbmsCentralRepo.CREATION_SCHEMA_MINOR_VERSION_KEY + "', '" + SOFTWARE_CR_DB_SCHEMA_VERSION.getMinor() + "')");
// Create a separate instance and reference table for each artifact type
List<CorrelationAttributeInstance.Type> DEFAULT_CORRELATION_TYPES = CorrelationAttributeInstance.getDefaultCorrelationTypes();
String reference_type_dbname;
String instance_type_dbname;
for (CorrelationAttributeInstance.Type type : DEFAULT_CORRELATION_TYPES) {
reference_type_dbname = CentralRepoDbUtil.correlationTypeToReferenceTableName(type);
instance_type_dbname = CentralRepoDbUtil.correlationTypeToInstanceTableName(type);
stmt.execute(String.format(createArtifactInstancesTableTemplate, instance_type_dbname, instance_type_dbname));
stmt.execute(String.format(instancesCaseIdIdx, instance_type_dbname, instance_type_dbname));
stmt.execute(String.format(instancesDatasourceIdIdx, instance_type_dbname, instance_type_dbname));
stmt.execute(String.format(instancesValueIdx, instance_type_dbname, instance_type_dbname));
stmt.execute(String.format(instancesKnownStatusIdx, instance_type_dbname, instance_type_dbname));
stmt.execute(String.format(instancesObjectIdIdx, instance_type_dbname, instance_type_dbname));
// FUTURE: allow more than the FILES type
if (type.getId() == CorrelationAttributeInstance.FILES_TYPE_ID) {
stmt.execute(String.format(createReferenceTypesTableTemplate.toString(), reference_type_dbname, reference_type_dbname));
stmt.execute(String.format(referenceTypesIdx1, reference_type_dbname, reference_type_dbname));
stmt.execute(String.format(referenceTypesIdx2, reference_type_dbname, reference_type_dbname));
}
}
} catch (SQLException ex) {
LOGGER.log(Level.SEVERE, "Error initializing db schema.", ex); // NON-NLS
return false;
} catch (CentralRepoException ex) {
LOGGER.log(Level.SEVERE, "Error getting default correlation types. Likely due to one or more Type's with an invalid db table name."); // NON-NLS
return false;
} finally {
CentralRepoDbUtil.closeConnection(conn);
}
return true;
}
/**
* Get the template String for creating a new _instances table in a Sqlite
* central repository. %s will exist in the template where the name of the
* new table will be addedd.
*
* @return a String which is a template for cretating a new _instances table
*/
static String getCreateArtifactInstancesTableTemplate() {
// Each "%s" will be replaced with the relevant TYPE_instances table name.
return "CREATE TABLE IF NOT EXISTS %s (id integer primary key autoincrement NOT NULL,"
+ "case_id integer NOT NULL,data_source_id integer NOT NULL,value text NOT NULL,"
+ "file_path text NOT NULL,known_status integer NOT NULL,comment text,file_obj_id integer,"
+ "CONSTRAINT %s_multi_unique UNIQUE(data_source_id, value, file_path) ON CONFLICT IGNORE,"
+ "foreign key (case_id) references cases(id) ON UPDATE SET NULL ON DELETE SET NULL,"
+ "foreign key (data_source_id) references data_sources(id) ON UPDATE SET NULL ON DELETE SET NULL)";
}
/**
* Get the statement String for creating a new data_sources table in a
* Sqlite central repository.
*
* @return a String which is a statement for cretating a new data_sources
* table
*/
static String getCreateDataSourcesTableStatement() {
return "CREATE TABLE IF NOT EXISTS data_sources (id integer primary key autoincrement NOT NULL,"
+ "case_id integer NOT NULL,device_id text NOT NULL,name text NOT NULL,datasource_obj_id integer,"
+ "md5 text DEFAULT NULL,sha1 text DEFAULT NULL,sha256 text DEFAULT NULL,"
+ "foreign key (case_id) references cases(id) ON UPDATE SET NULL ON DELETE SET NULL,"
+ "CONSTRAINT datasource_unique UNIQUE (case_id, datasource_obj_id))";
}
/**
* Get the statement for creating an index on the name column of the
* data_sources table.
*
* @return a String which is a statement for adding an index on the name
* column of the data_sources table.
*/
static String getAddDataSourcesNameIndexStatement() {
return "CREATE INDEX IF NOT EXISTS data_sources_name ON data_sources (name)";
}
/**
* Get the statement for creating an index on the data_sources_object_id
* column of the data_sources table.
*
* @return a String which is a statement for adding an index on the
* data_sources_object_id column of the data_sources table.
*/
static String getAddDataSourcesObjectIdIndexStatement() {
return "CREATE INDEX IF NOT EXISTS data_sources_object_id ON data_sources (datasource_obj_id)";
}
/**
* Get the template for creating an index on the case_id column of an
* instance table. %s will exist in the template where the name of the new
* table will be addedd.
*
* @return a String which is a template for adding an index to the case_id
* column of a _instances table
*/
static String getAddCaseIdIndexTemplate() {
// Each "%s" will be replaced with the relevant TYPE_instances table name.
return "CREATE INDEX IF NOT EXISTS %s_case_id ON %s (case_id)";
}
/**
* Get the template for creating an index on the data_source_id column of an
* instance table. %s will exist in the template where the name of the new
* table will be addedd.
*
* @return a String which is a template for adding an index to the
* data_source_id column of a _instances table
*/
static String getAddDataSourceIdIndexTemplate() {
// Each "%s" will be replaced with the relevant TYPE_instances table name.
return "CREATE INDEX IF NOT EXISTS %s_data_source_id ON %s (data_source_id)";
}
/**
* Get the template for creating an index on the value column of an instance
* table. %s will exist in the template where the name of the new table will
* be addedd.
*
* @return a String which is a template for adding an index to the value
* column of a _instances table
*/
static String getAddValueIndexTemplate() {
// Each "%s" will be replaced with the relevant TYPE_instances table name.
return "CREATE INDEX IF NOT EXISTS %s_value ON %s (value)";
}
/**
* Get the template for creating an index on the known_status column of an
* instance table. %s will exist in the template where the name of the new
* table will be addedd.
*
* @return a String which is a template for adding an index to the
* known_status column of a _instances table
*/
static String getAddKnownStatusIndexTemplate() {
// Each "%s" will be replaced with the relevant TYPE_instances table name.
return "CREATE INDEX IF NOT EXISTS %s_value_known_status ON %s (value, known_status)";
}
/**
* Get the template for creating an index on the file_obj_id column of an
* instance table. %s will exist in the template where the name of the new
* table will be addedd.
*
* @return a String which is a template for adding an index to the
* file_obj_id column of a _instances table
*/
static String getAddObjectIdIndexTemplate() {
// Each "%s" will be replaced with the relevant TYPE_instances table name.
return "CREATE INDEX IF NOT EXISTS %s_file_obj_id ON %s (file_obj_id)";
}
public boolean insertDefaultDatabaseContent() {
Connection conn = getEphemeralConnection();
if (null == conn) {
return false;
}
boolean result = CentralRepoDbUtil.insertDefaultCorrelationTypes(conn) && CentralRepoDbUtil.insertDefaultOrganization(conn);
CentralRepoDbUtil.closeConnection(conn);
return result;
}
boolean isChanged() { boolean isChanged() {
String dbNameString = ModuleSettings.getConfigSetting("CentralRepository", "db.sqlite.dbName"); // NON-NLS String dbNameString = ModuleSettings.getConfigSetting("CentralRepository", "db.sqlite.dbName"); // NON-NLS
String dbDirectoryString = ModuleSettings.getConfigSetting("CentralRepository", "db.sqlite.dbDirectory"); // NON-NLS String dbDirectoryString = ModuleSettings.getConfigSetting("CentralRepository", "db.sqlite.dbDirectory"); // NON-NLS

View File

@ -133,7 +133,7 @@
<Component id="lbUserName" alignment="0" min="-2" max="-2" attributes="0"/> <Component id="lbUserName" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="lbPort" alignment="0" min="-2" max="-2" attributes="0"/> <Component id="lbPort" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="103" alignment="0" groupAlignment="1" max="-2" attributes="0"> <Group type="103" alignment="0" groupAlignment="1" max="-2" attributes="0">
<Component id="lbDatabaseDesc" alignment="0" max="32767" attributes="0"/> <Component id="lbDatabaseDesc" alignment="0" pref="94" max="32767" attributes="0"/>
<Component id="lbUserPassword" alignment="0" max="32767" attributes="0"/> <Component id="lbUserPassword" alignment="0" max="32767" attributes="0"/>
</Group> </Group>
</Group> </Group>
@ -410,4 +410,4 @@
</SubComponents> </SubComponents>
</Container> </Container>
</SubComponents> </SubComponents>
</Form> </Form>

View File

@ -35,6 +35,7 @@ import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener; import javax.swing.event.DocumentListener;
import javax.swing.filechooser.FileFilter; import javax.swing.filechooser.FileFilter;
import org.netbeans.spi.options.OptionsPanelController; import org.netbeans.spi.options.OptionsPanelController;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
import org.openide.windows.WindowManager; import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.corecomponents.TextPrompt; import org.sleuthkit.autopsy.corecomponents.TextPrompt;
@ -45,6 +46,7 @@ import static org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoPlatf
import org.sleuthkit.autopsy.centralrepository.datamodel.PostgresCentralRepoSettings; import org.sleuthkit.autopsy.centralrepository.datamodel.PostgresCentralRepoSettings;
import org.sleuthkit.autopsy.centralrepository.datamodel.SqliteCentralRepoSettings; import org.sleuthkit.autopsy.centralrepository.datamodel.SqliteCentralRepoSettings;
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
import org.sleuthkit.autopsy.centralrepository.datamodel.RdbmsCentralRepoSchemaFactory;
/** /**
* Configuration dialog for Central Repository database settings. * Configuration dialog for Central Repository database settings.
@ -447,12 +449,19 @@ public class EamDbSettingsDialog extends JDialog {
dbCreated = dbSettingsPostgres.createDatabase(); dbCreated = dbSettingsPostgres.createDatabase();
} }
if (dbCreated) { if (dbCreated) {
result = dbSettingsPostgres.initializeDatabaseSchema() try {
&& dbSettingsPostgres.insertDefaultDatabaseContent(); RdbmsCentralRepoSchemaFactory centralRepoSchemaFactory = new RdbmsCentralRepoSchemaFactory(selectedPlatform);
result = centralRepoSchemaFactory.initializeDatabaseSchema()
&& centralRepoSchemaFactory.insertDefaultDatabaseContent();
} catch (CentralRepoException ex) {
logger.log( Level.SEVERE, "Unable to initialize database schema or insert contents into Postgres central repository.", ex);
}
} }
if (!result) { if (!result) {
// Remove the incomplete database // Remove the incomplete database
if (dbCreated) { if (dbCreated) {
// RAMAN TBD: migrate deleteDatabase() to RdbmsCentralRepoSchemaFactory
dbSettingsPostgres.deleteDatabase(); dbSettingsPostgres.deleteDatabase();
} }
@ -469,8 +478,14 @@ public class EamDbSettingsDialog extends JDialog {
dbCreated = dbSettingsSqlite.createDbDirectory(); dbCreated = dbSettingsSqlite.createDbDirectory();
} }
if (dbCreated) { if (dbCreated) {
result = dbSettingsSqlite.initializeDatabaseSchema() try {
&& dbSettingsSqlite.insertDefaultDatabaseContent(); RdbmsCentralRepoSchemaFactory centralRepoSchemaFactory = new RdbmsCentralRepoSchemaFactory(selectedPlatform);
result = centralRepoSchemaFactory.initializeDatabaseSchema()
&& centralRepoSchemaFactory.insertDefaultDatabaseContent();
} catch (CentralRepoException ex) {
logger.log( Level.SEVERE, "Unable to initialize database schema or insert contents into SQLite central repository.", ex);
}
} }
if (!result) { if (!result) {
if (dbCreated) { if (dbCreated) {