mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-14 17:06:16 +00:00
Interim commit - isolated scheme creation code from DBSettings classes and put them in the new RdmsCentralRepoSchemaFactory.
This commit is contained in:
parent
ab81c1fe79
commit
cc7ed224ff
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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.
|
||||||
*
|
*
|
||||||
|
@ -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
|
||||||
|
@ -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>
|
||||||
|
@ -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) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user