diff --git a/bindings/java/src/org/sleuthkit/datamodel/CaseDatabaseFactory.java b/bindings/java/src/org/sleuthkit/datamodel/CaseDatabaseFactory.java index f6bc4bf65d09d57e1868307ca9da639d39bc049d..5adb2b2fd0b12c31151e41787c0faecb0e3094fd 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/CaseDatabaseFactory.java +++ b/bindings/java/src/org/sleuthkit/datamodel/CaseDatabaseFactory.java @@ -25,9 +25,9 @@ import java.sql.Statement; import java.util.logging.Level; import java.util.logging.Logger; -import org.sleuthkit.datamodel.databaseutils.DatabaseQueryHelper; -import org.sleuthkit.datamodel.databaseutils.PostgreSQLQueryHelper; -import org.sleuthkit.datamodel.databaseutils.SQLiteQueryHelper; +import java.util.Properties; +import org.sleuthkit.datamodel.SQLHelper.PostgreSQLHelper; +import org.sleuthkit.datamodel.SQLHelper.SQLiteHelper; /** * @@ -35,7 +35,7 @@ class CaseDatabaseFactory { private static final Logger logger = Logger.getLogger(CaseDatabaseFactory.class.getName()); - private final DatabaseQueryHelper dbQueryHelper; + private final SQLHelper dbQueryHelper; private final DbCreationHelper dbCreationHelper; /** @@ -44,7 +44,7 @@ class CaseDatabaseFactory { * @param dbPath Full path to the database */ CaseDatabaseFactory(String dbPath) { - this.dbQueryHelper = new SQLiteQueryHelper(); + this.dbQueryHelper = new SQLiteHelper(); this.dbCreationHelper = new SQLiteDbCreationHelper(dbPath); } @@ -57,11 +57,10 @@ class CaseDatabaseFactory { * database server. Use getDatabaseName to get the * created name. * @param info The information to connect to the database. - * @param caseDirPath The case directory path. */ - CaseDatabaseFactory(String caseName, CaseDbConnectionInfo info, String caseDirPath) { - this.dbQueryHelper = new PostgreSQLQueryHelper(); - this.dbCreationHelper = new PostgreSQLDbCreationHelper(caseName, info, caseDirPath); + CaseDatabaseFactory(String caseName, CaseDbConnectionInfo info) { + this.dbQueryHelper = new PostgreSQLHelper(); + this.dbCreationHelper = new PostgreSQLDbCreationHelper(caseName, info); } /** @@ -71,7 +70,6 @@ class CaseDatabaseFactory { * @throws TskCoreException */ void createCaseDatabase() throws TskCoreException { - createDatabase(); initializeSchema(); } @@ -108,8 +106,7 @@ private void initializeSchema() throws TskCoreException { dbCreationHelper.performPostTableInitialization(conn); // Add indexes - createIndexes(conn); - + addIndexes(conn); } finally { try { conn.close(); @@ -127,18 +124,8 @@ private void initializeSchema() throws TskCoreException { * @throws TskCoreException */ private void addDbInfo(Connection conn) throws TskCoreException { - - /* Version of code in number form. - * Upper byte is A, next is B, and next byte is C in version A.B.C. - * Lowest byte is 0xff, except in beta releases, in which case it - * increments from 1. - * For example, 3.1.2 would be stored as 0x030102FF. - */ CaseDbSchemaVersionNumber version = SleuthkitCase.CURRENT_DB_SCHEMA_VERSION; - long tskVersionNum = version.getMajor() << 24 - | version.getMinor() << 16 - | version.getPatch() << 8 - | 0xff; + long tskVersionNum = 0; // This is the current version of TSK (not the DB schema version) try (Statement stmt = conn.createStatement()) { stmt.execute("CREATE TABLE tsk_db_info (schema_ver INTEGER, tsk_ver INTEGER, schema_minor_ver INTEGER)"); @@ -176,22 +163,28 @@ private void addTables(Connection conn) throws TskCoreException { + "sequence INTEGER NOT NULL, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE)"); stmt.execute("CREATE TABLE tsk_vs_info (obj_id " + dbQueryHelper.getPrimaryKey() + " PRIMARY KEY, vs_type INTEGER NOT NULL, " - + "img_offset " + dbQueryHelper.getBigIntType() + " NOT NULL, block_size BIGINT NOT NULL, " + + "img_offset " + dbQueryHelper.getBigIntType() + " NOT NULL, block_size " + dbQueryHelper.getBigIntType() + " NOT NULL, " + "FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE)"); stmt.execute("CREATE TABLE data_source_info (obj_id " + dbQueryHelper.getBigIntType() + " PRIMARY KEY, device_id TEXT NOT NULL, " + "time_zone TEXT NOT NULL, acquisition_details TEXT, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE)"); stmt.execute("CREATE TABLE tsk_fs_info (obj_id " + dbQueryHelper.getPrimaryKey() + " PRIMARY KEY, " - + "img_offset " + dbQueryHelper.getBigIntType() + " NOT NULL, fs_type INTEGER NOT NULL, block_size BIGINT NOT NULL, " - + "block_count BIGINT NOT NULL, root_inum BIGINT NOT NULL, first_inum BIGINT NOT NULL, last_inum BIGINT NOT NULL, " + + "img_offset " + dbQueryHelper.getBigIntType() + " NOT NULL, fs_type INTEGER NOT NULL, " + + "block_size " + dbQueryHelper.getBigIntType() + " NOT NULL, " + + "block_count " + dbQueryHelper.getBigIntType() + " NOT NULL, root_inum " + dbQueryHelper.getBigIntType() + " NOT NULL, " + + "first_inum " + dbQueryHelper.getBigIntType() + " NOT NULL, last_inum " + dbQueryHelper.getBigIntType() + " NOT NULL, " + "display_name TEXT, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE)"); stmt.execute("CREATE TABLE tsk_files (obj_id " + dbQueryHelper.getPrimaryKey() + " PRIMARY KEY, " - + "fs_obj_id " + dbQueryHelper.getBigIntType() + ", data_source_obj_id BIGINT NOT NULL, attr_type INTEGER, attr_id INTEGER, " - + "name TEXT NOT NULL, meta_addr BIGINT, meta_seq BIGINT, type INTEGER, has_layout INTEGER, has_path INTEGER, " - + "dir_type INTEGER, meta_type INTEGER, dir_flags INTEGER, meta_flags INTEGER, size BIGINT, ctime BIGINT, " - + "crtime BIGINT, atime BIGINT, mtime BIGINT, mode INTEGER, uid INTEGER, gid INTEGER, md5 TEXT, known INTEGER, " + + "fs_obj_id " + dbQueryHelper.getBigIntType() + ", data_source_obj_id " + dbQueryHelper.getBigIntType() + " NOT NULL, " + + "attr_type INTEGER, attr_id INTEGER, " + + "name TEXT NOT NULL, meta_addr " + dbQueryHelper.getBigIntType() + ", meta_seq " + dbQueryHelper.getBigIntType() + ", " + + "type INTEGER, has_layout INTEGER, has_path INTEGER, " + + "dir_type INTEGER, meta_type INTEGER, dir_flags INTEGER, meta_flags INTEGER, size " + dbQueryHelper.getBigIntType() + ", " + + "ctime " + dbQueryHelper.getBigIntType() + ", " + + "crtime " + dbQueryHelper.getBigIntType() + ", atime " + dbQueryHelper.getBigIntType() + ", " + + "mtime " + dbQueryHelper.getBigIntType() + ", mode INTEGER, uid INTEGER, gid INTEGER, md5 TEXT, known INTEGER, " + "parent_path TEXT, mime_type TEXT, extension TEXT, " + "FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, " + "FOREIGN KEY(fs_obj_id) REFERENCES tsk_fs_info(obj_id) ON DELETE CASCADE, " @@ -200,7 +193,7 @@ private void addTables(Connection conn) throws TskCoreException { stmt.execute("CREATE TABLE file_encoding_types (encoding_type INTEGER PRIMARY KEY, name TEXT NOT NULL)"); stmt.execute("CREATE TABLE tsk_files_path (obj_id " + dbQueryHelper.getPrimaryKey() + " PRIMARY KEY, path TEXT NOT NULL, " - + "encoding_type INTEGER, FOREIGN KEY(encoding_type) references file_encoding_types(encoding_type), " + + "encoding_type INTEGER NOT NULL, FOREIGN KEY(encoding_type) references file_encoding_types(encoding_type), " + "FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE)"); stmt.execute("CREATE TABLE tsk_files_derived (obj_id " + dbQueryHelper.getPrimaryKey() + " PRIMARY KEY, " @@ -240,7 +233,8 @@ private void addTables(Connection conn) throws TskCoreException { * http://www.postgresql.org/docs/9.4/static/libpq-example.html */ stmt.execute("CREATE TABLE blackboard_attributes (artifact_id " + dbQueryHelper.getBigIntType() + " NOT NULL, " - + "artifact_type_id BIGINT NOT NULL, source TEXT, context TEXT, attribute_type_id BIGINT NOT NULL, " + + "artifact_type_id " + dbQueryHelper.getBigIntType() + " NOT NULL, " + + "source TEXT, context TEXT, attribute_type_id " + dbQueryHelper.getBigIntType() + " NOT NULL, " + "value_type INTEGER NOT NULL, value_byte " + dbQueryHelper.getBlobType() + ", " + "value_text TEXT, value_int32 INTEGER, value_int64 " + dbQueryHelper.getBigIntType() + ", value_double NUMERIC(20, 10), " + "FOREIGN KEY(artifact_id) REFERENCES blackboard_artifacts(artifact_id) ON DELETE CASCADE, " @@ -248,7 +242,8 @@ private void addTables(Connection conn) throws TskCoreException { + "FOREIGN KEY(attribute_type_id) REFERENCES blackboard_attribute_types(attribute_type_id))"); stmt.execute("CREATE TABLE tsk_vs_parts (obj_id " + dbQueryHelper.getPrimaryKey() + " PRIMARY KEY, " - + "addr " + dbQueryHelper.getBigIntType() + " NOT NULL, start BIGINT NOT NULL, length BIGINT NOT NULL, " + + "addr " + dbQueryHelper.getBigIntType() + " NOT NULL, start " + dbQueryHelper.getBigIntType() + " NOT NULL, " + + "length " + dbQueryHelper.getBigIntType() + " NOT NULL, " + dbQueryHelper.getVSDescColName() + " TEXT, " + "flags INTEGER NOT NULL, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE);"); @@ -265,7 +260,8 @@ private void addTables(Connection conn) throws TskCoreException { stmt.execute("CREATE TABLE ingest_jobs (ingest_job_id " + dbQueryHelper.getPrimaryKey() + " PRIMARY KEY, " + "obj_id " + dbQueryHelper.getBigIntType() + " NOT NULL, host_name TEXT NOT NULL, " - + "start_date_time BIGINT NOT NULL, end_date_time BIGINT NOT NULL, status_id INTEGER NOT NULL, " + + "start_date_time " + dbQueryHelper.getBigIntType() + " NOT NULL, " + + "end_date_time " + dbQueryHelper.getBigIntType() + " NOT NULL, status_id INTEGER NOT NULL, " + "settings_dir TEXT, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, " + "FOREIGN KEY(status_id) REFERENCES ingest_job_status_types(type_id) ON DELETE CASCADE);"); @@ -286,10 +282,11 @@ private void addTables(Connection conn) throws TskCoreException { + "UNIQUE(account_type_id, account_unique_identifier), " + "FOREIGN KEY(account_type_id) REFERENCES account_types(account_type_id))"); - stmt.execute("CREATE TABLE account_relationships (relationship_id " + dbQueryHelper.getPrimaryKey() + " PRIMARY KEY, " + stmt.execute("CREATE TABLE account_relationships (relationship_id " + dbQueryHelper.getPrimaryKey() + " PRIMARY KEY, " + "account1_id INTEGER NOT NULL, account2_id INTEGER NOT NULL, " + "relationship_source_obj_id " + dbQueryHelper.getBigIntType() + " NOT NULL, " - + "date_time BIGINT, relationship_type INTEGER NOT NULL, data_source_obj_id BIGINT NOT NULL, " + + "date_time " + dbQueryHelper.getBigIntType() + ", relationship_type INTEGER NOT NULL, " + + "data_source_obj_id " + dbQueryHelper.getBigIntType() + " NOT NULL, " + "UNIQUE(account1_id, account2_id, relationship_source_obj_id), " + "FOREIGN KEY(account1_id) REFERENCES accounts(account_id), " + "FOREIGN KEY(account2_id) REFERENCES accounts(account_id), " @@ -301,15 +298,14 @@ private void addTables(Connection conn) throws TskCoreException { + " display_name TEXT UNIQUE NOT NULL , " + " super_type_id INTEGER REFERENCES tsk_event_types(event_type_id) )"); - stmt.execute( - "INSERT INTO tsk_event_types(event_type_id, display_name, super_type_id) VALUES(0, 'Event Types', null);" - + "INSERT INTO tsk_event_types(event_type_id, display_name, super_type_id) VALUES(1, 'File System', 0);" - + "INSERT INTO tsk_event_types(event_type_id, display_name, super_type_id) VALUES(2, 'Web Activity', 0);" - + "INSERT INTO tsk_event_types(event_type_id, display_name, super_type_id) VALUES(3, 'Misc Types', 0);" - + "INSERT INTO tsk_event_types(event_type_id, display_name, super_type_id) VALUES(4, 'Modified', 1);" - + "INSERT INTO tsk_event_types(event_type_id, display_name, super_type_id) VALUES(5, 'Accessed', 1);" - + "INSERT INTO tsk_event_types(event_type_id, display_name, super_type_id) VALUES(6, 'Created', 1);" - + "INSERT INTO tsk_event_types(event_type_id, display_name, super_type_id) VALUES(7, 'Changed', 1);"); + stmt.execute("INSERT INTO tsk_event_types(event_type_id, display_name, super_type_id) VALUES(0, 'Event Types', null)"); + stmt.execute("INSERT INTO tsk_event_types(event_type_id, display_name, super_type_id) VALUES(1, 'File System', 0)"); + stmt.execute("INSERT INTO tsk_event_types(event_type_id, display_name, super_type_id) VALUES(2, 'Web Activity', 0)"); + stmt.execute("INSERT INTO tsk_event_types(event_type_id, display_name, super_type_id) VALUES(3, 'Misc Types', 0)"); + stmt.execute("INSERT INTO tsk_event_types(event_type_id, display_name, super_type_id) VALUES(4, 'Modified', 1)"); + stmt.execute("INSERT INTO tsk_event_types(event_type_id, display_name, super_type_id) VALUES(5, 'Accessed', 1)"); + stmt.execute("INSERT INTO tsk_event_types(event_type_id, display_name, super_type_id) VALUES(6, 'Created', 1)"); + stmt.execute("INSERT INTO tsk_event_types(event_type_id, display_name, super_type_id) VALUES(7, 'Changed', 1)"); /* * Regarding the timeline event tables schema, note that several columns * in the tsk_event_descriptions table seem, at first glance, to be @@ -350,22 +346,23 @@ private void addTables(Connection conn) throws TskCoreException { + "login_name TEXT NOT NULL, display_name TEXT, UNIQUE(login_name))"); stmt.execute("CREATE TABLE content_tags (tag_id " + dbQueryHelper.getPrimaryKey() + " PRIMARY KEY, " - + "obj_id " + dbQueryHelper.getBigIntType() + " NOT NULL, tag_name_id BIGINT NOT NULL, " - + "comment TEXT NOT NULL, begin_byte_offset BIGINT NOT NULL, end_byte_offset BIGINT NOT NULL, " - + "examiner_id BIGINT, " - + "FOREIGN KEY(examiner_id) REFERENCES tsk_examiners(examiner_id), " - + "FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, " - + "FOREIGN KEY(tag_name_id) REFERENCES tag_names(tag_name_id))"); + + "obj_id " + dbQueryHelper.getBigIntType() + " NOT NULL, tag_name_id " + dbQueryHelper.getBigIntType() + " NOT NULL, " + + "comment TEXT NOT NULL, begin_byte_offset " + dbQueryHelper.getBigIntType() + " NOT NULL, " + + "end_byte_offset " + dbQueryHelper.getBigIntType() + " NOT NULL, " + + "examiner_id " + dbQueryHelper.getBigIntType() + ", " + + "FOREIGN KEY(examiner_id) REFERENCES tsk_examiners(examiner_id), " + + "FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, " + + "FOREIGN KEY(tag_name_id) REFERENCES tag_names(tag_name_id))"); stmt.execute("CREATE TABLE blackboard_artifact_tags (tag_id " + dbQueryHelper.getPrimaryKey() + " PRIMARY KEY, " - + "artifact_id " + dbQueryHelper.getBigIntType() + " NOT NULL, tag_name_id BIGINT NOT NULL, " - + "comment TEXT NOT NULL, examiner_id BIGINT, " + + "artifact_id " + dbQueryHelper.getBigIntType() + " NOT NULL, tag_name_id " + dbQueryHelper.getBigIntType() + " NOT NULL, " + + "comment TEXT NOT NULL, examiner_id " + dbQueryHelper.getBigIntType() + ", " + "FOREIGN KEY(examiner_id) REFERENCES tsk_examiners(examiner_id), " + "FOREIGN KEY(artifact_id) REFERENCES blackboard_artifacts(artifact_id) ON DELETE CASCADE, " + "FOREIGN KEY(tag_name_id) REFERENCES tag_names(tag_name_id))"); stmt.execute("CREATE TABLE tsk_file_layout (obj_id " + dbQueryHelper.getBigIntType() + " NOT NULL, " - + "byte_start BIGINT NOT NULL, byte_len BIGINT NOT NULL, " + + "byte_start " + dbQueryHelper.getBigIntType() + " NOT NULL, byte_len " + dbQueryHelper.getBigIntType() + " NOT NULL, " + "sequence INTEGER NOT NULL, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE);"); } catch (SQLException ex) { @@ -380,7 +377,38 @@ private void addTables(Connection conn) throws TskCoreException { * @throws TskCoreException */ private void addIndexes(Connection conn) throws TskCoreException { - + try (Statement stmt = conn.createStatement()) { + // tsk_objects index + stmt.execute("CREATE INDEX parObjId ON tsk_objects(par_obj_id)"); + + // file layout index + stmt.execute("CREATE INDEX layout_objID ON tsk_file_layout(obj_id)"); + + // blackboard indexes + stmt.execute("CREATE INDEX artifact_objID ON blackboard_artifacts(obj_id)"); + stmt.execute("CREATE INDEX artifact_artifact_objID ON blackboard_artifacts(artifact_obj_id)"); + stmt.execute("CREATE INDEX artifact_typeID ON blackboard_artifacts(artifact_type_id)"); + stmt.execute("CREATE INDEX attrsArtifactID ON blackboard_attributes(artifact_id)"); + + //file type indexes + stmt.execute("CREATE INDEX mime_type ON tsk_files(dir_type,mime_type,type)"); //mime type + stmt.execute("CREATE INDEX file_extension ON tsk_files(extension)"); //file extenssion + stmt.execute("CREATE INDEX relationships_account1 ON account_relationships(account1_id)"); + stmt.execute("CREATE INDEX relationships_account2 ON account_relationships(account2_id)"); + stmt.execute("CREATE INDEX relationships_relationship_source_obj_id ON account_relationships(relationship_source_obj_id)"); + stmt.execute("CREATE INDEX relationships_date_time ON account_relationships(date_time)"); + stmt.execute("CREATE INDEX relationships_relationship_type ON account_relationships(relationship_type)"); + stmt.execute("CREATE INDEX relationships_data_source_obj_id ON account_relationships(data_source_obj_id)"); + + //tsk_events indices + stmt.execute("CREATE INDEX events_data_source_obj_id ON tsk_event_descriptions(data_source_obj_id)"); + stmt.execute("CREATE INDEX events_content_obj_id ON tsk_event_descriptions(content_obj_id)"); + stmt.execute("CREATE INDEX events_artifact_id ON tsk_event_descriptions(artifact_id)"); + stmt.execute("CREATE INDEX events_sub_type_time ON tsk_events(event_type_id, time)"); + stmt.execute("CREATE INDEX events_time ON tsk_events(time)"); + } catch (SQLException ex) { + throw new TskCoreException("Error initializing db_info tables", ex); + } } private abstract class DbCreationHelper { @@ -393,23 +421,21 @@ private abstract class DbCreationHelper { abstract void createDatabase() throws TskCoreException; /** - * Get an connection to the database + * Get an connection to the case database * * @return the connection */ abstract Connection getConnection(); /** - * Do initialization before creating the tables. + * Do any needed initialization before creating the tables. * This is where SQLite pragmas are set up. * * @param conn The database connection * * @throws TskCoreException */ - void performPreInitialization(Connection conn) throws TskCoreException { - // By default do nothing - } + abstract void performPreInitialization(Connection conn) throws TskCoreException; /** * Do any additional steps after the tables are created. @@ -417,30 +443,94 @@ void performPreInitialization(Connection conn) throws TskCoreException { * @param conn The database connection * @throws TskCoreException */ - void performPostTableInitialization(Connection conn) throws TskCoreException { - // By default do nothing - } + abstract void performPostTableInitialization(Connection conn) throws TskCoreException; } private class PostgreSQLDbCreationHelper extends DbCreationHelper { - PostgreSQLDbCreationHelper(String caseName, CaseDbConnectionInfo info, String caseDirPath) { - + private final static String JDBC_BASE_URI = "jdbc:postgresql://"; // NON-NLS + private final static String JDBC_DRIVER = "org.postgresql.Driver"; // NON-NLS + + final private String caseName; + final private CaseDbConnectionInfo info; + + PostgreSQLDbCreationHelper(String caseName, CaseDbConnectionInfo info) { + this.caseName = caseName; + this.info = info; } @Override - void createDatabase() {} + void createDatabase() throws TskCoreException{ + Connection conn = getPostgresConnection(); + if (conn == null) { + throw new TskCoreException("Error connecting to the PostgreSQL server"); + } + + try(Statement stmt = conn.createStatement()) { + stmt.execute("CREATE DATABASE \"" + caseName + "\" WITH ENCODING='UTF8'"); + } catch (SQLException ex) { + throw new TskCoreException("Error creating PostgreSQL case " + caseName, ex); + } finally { + try { + conn.close(); + } catch (SQLException ex) { + logger.log(Level.SEVERE, "Error closing connection.", ex); + } + } + } @Override - Connection getConnection() { return null; } + Connection getConnection() { + return getConnection(caseName); + } + + /** + * Connects to the "postgres" database for creating new databases. + * + * @return the connection to the "postgres" database + */ + Connection getPostgresConnection() { + return getConnection("postgres"); + } + + Connection getConnection(String databaseName) { + + StringBuilder url = new StringBuilder(); + url.append(JDBC_BASE_URI) + .append(info.getHost()) + .append("/") // NON-NLS + .append(databaseName); + + Connection conn; + try { + Properties props = new Properties(); + props.setProperty("user", info.getUserName()); + props.setProperty("password", info.getPassword()); + + Class.forName(JDBC_DRIVER); + conn = DriverManager.getConnection(url.toString(), props); + } catch (ClassNotFoundException | SQLException ex) { + // TODO: Determine why a connection failure (ConnectionException) re-throws + // the SQLException and does not print this log message? + logger.log(Level.SEVERE, "Failed to acquire ephemeral connection to postgresql."); // NON-NLS + conn = null; + } + return conn; + } + + @Override + void performPreInitialization(Connection conn) throws TskCoreException { + // Nothing to do here for PostgreSQL + } @Override void performPostTableInitialization(Connection conn) throws TskCoreException { - - // TODO TODO - //stmt.execute("ALTER SEQUENCE blackboard_artifacts_artifact_id_seq minvalue -9223372036854775808 restart with -9223372036854775808"); + try (Statement stmt = conn.createStatement()) { + stmt.execute("ALTER SEQUENCE blackboard_artifacts_artifact_id_seq minvalue -9223372036854775808 restart with -9223372036854775808"); + } catch (SQLException ex) { + throw new TskCoreException("Error setting pragmas", ex); + } } - } private class SQLiteDbCreationHelper extends DbCreationHelper { @@ -517,5 +607,10 @@ void performPreInitialization(Connection conn) throws TskCoreException { } */ } + + @Override + void performPostTableInitialization(Connection conn) throws TskCoreException { + // Nothing to do here for SQLite + } } } diff --git a/bindings/java/src/org/sleuthkit/datamodel/databaseutils/DatabaseQueryHelper.java b/bindings/java/src/org/sleuthkit/datamodel/SQLHelper.java similarity index 54% rename from bindings/java/src/org/sleuthkit/datamodel/databaseutils/DatabaseQueryHelper.java rename to bindings/java/src/org/sleuthkit/datamodel/SQLHelper.java index 91247144d9cd401b1400ed11f7f70cbe82421a6f..47c0b5066ae27963a1dceb8612c5cad56bc3da21 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/databaseutils/DatabaseQueryHelper.java +++ b/bindings/java/src/org/sleuthkit/datamodel/SQLHelper.java @@ -16,12 +16,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.datamodel.databaseutils; +package org.sleuthkit.datamodel; /** * Interface for classes to help create queries for SQLite or PostgreSQL */ -public interface DatabaseQueryHelper { +interface SQLHelper { // Get the type for the primary key String getPrimaryKey(); @@ -32,6 +32,54 @@ public interface DatabaseQueryHelper { // Get the type for blob-type data String getBlobType(); - // Get the description column name for the tsk_vs_parts table + // Get the description column name for the tsk_vs_parts table. + // This varies between SQLite and PostgreSQL. String getVSDescColName(); -} + + + class PostgreSQLHelper implements SQLHelper { + + @Override + public String getPrimaryKey() { + return "BIGSERIAL"; + } + + @Override + public String getBigIntType() { + return "BIGINT"; + } + + @Override + public String getBlobType() { + return "BYTEA"; + } + + @Override + public String getVSDescColName() { + return "descr"; + } + } + + class SQLiteHelper implements SQLHelper { + + @Override + public String getPrimaryKey() { + return "INTEGER"; + } + + @Override + public String getBigIntType() { + return "INTEGER"; + } + + @Override + public String getBlobType() { + return "BLOB"; + } + + @Override + public String getVSDescColName() { + return "desc"; + } + } +} \ No newline at end of file diff --git a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java index 1cb42fbe2214daf9e3130441ada97cc68ae7cae0..b598a6d56863d5006b96db13fec28eb7ce7cf945 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java +++ b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java @@ -80,9 +80,6 @@ import org.sleuthkit.datamodel.TskData.TSK_FS_META_TYPE_ENUM; import org.sleuthkit.datamodel.TskData.TSK_FS_NAME_FLAG_ENUM; import org.sleuthkit.datamodel.TskData.TSK_FS_NAME_TYPE_ENUM; -import org.sleuthkit.datamodel.databaseutils.DatabaseQueryHelper; -import org.sleuthkit.datamodel.databaseutils.PostgreSQLQueryHelper; -import org.sleuthkit.datamodel.databaseutils.SQLiteQueryHelper; import org.sqlite.SQLiteConfig; import org.sqlite.SQLiteDataSource; @@ -186,7 +183,6 @@ public class SleuthkitCase { private final String dbPath; private final DbType dbType; private final String caseDirPath; - private DatabaseQueryHelper dBqueryHelper; private SleuthkitJNI.CaseDbHandle caseHandle; private String dbBackupPath; private Map<Integer, BlackboardArtifact.Type> typeIdToArtifactTypeMap; @@ -356,15 +352,6 @@ private void init() throws Exception { typeIdToAttributeTypeMap = new ConcurrentHashMap<>(); typeNameToArtifactTypeMap = new ConcurrentHashMap<>(); typeNameToAttributeTypeMap = new ConcurrentHashMap<>(); - - /* - * Set up the appropriate database helper - */ - if (dbType == DbType.POSTGRESQL) { - dBqueryHelper = new PostgreSQLQueryHelper(); - } else { - dBqueryHelper = new SQLiteQueryHelper(); - } /* * The following methods need to be called before updateDatabaseSchema @@ -2352,18 +2339,10 @@ public static SleuthkitCase openCase(String databaseName, CaseDbConnectionInfo i */ public static SleuthkitCase newCase(String dbPath) throws TskCoreException { try { - - File dbFile = new File(dbPath); - String testingDb = Paths.get(dbFile.getParent(), "testing.db").toString(); - CaseDatabaseFactory factory = new CaseDatabaseFactory(testingDb); - try { - factory.createCaseDatabase(); - } catch (TskCoreException ex) { - // Oh no - logger.log(Level.SEVERE, "Error in new case code", ex); - } - - SleuthkitJNI.CaseDbHandle caseHandle = SleuthkitJNI.newCaseDb(dbPath); + CaseDatabaseFactory factory = new CaseDatabaseFactory(dbPath); + factory.createCaseDatabase(); + + SleuthkitJNI.CaseDbHandle caseHandle = SleuthkitJNI.openCaseDb(dbPath); return new SleuthkitCase(dbPath, caseHandle, DbType.SQLITE); } catch (Exception ex) { throw new TskCoreException("Failed to create case database at " + dbPath, ex); @@ -2400,7 +2379,10 @@ public static SleuthkitCase newCase(String caseName, CaseDbConnectionInfo info, * the case. In this way, we obtain more detailed information if we * are able, but do not lose any information if unable. */ - SleuthkitJNI.CaseDbHandle caseHandle = SleuthkitJNI.newCaseDb(databaseName, info); + CaseDatabaseFactory factory = new CaseDatabaseFactory(databaseName, info); + factory.createCaseDatabase(); + + final SleuthkitJNI.CaseDbHandle caseHandle = SleuthkitJNI.openCaseDb(databaseName, info); return new SleuthkitCase(info.getHost(), Integer.parseInt(info.getPort()), databaseName, info.getUserName(), info.getPassword(), caseHandle, caseDirPath, info.getDbType()); } catch (PropertyVetoException exp) { diff --git a/bindings/java/src/org/sleuthkit/datamodel/databaseutils/PostgreSQLQueryHelper.java b/bindings/java/src/org/sleuthkit/datamodel/databaseutils/PostgreSQLQueryHelper.java deleted file mode 100644 index 41d2ed73c80d38437ee15aa4bf6f67c2f2a5dbd0..0000000000000000000000000000000000000000 --- a/bindings/java/src/org/sleuthkit/datamodel/databaseutils/PostgreSQLQueryHelper.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Sleuth Kit Data Model - * - * Copyright 2020 Basis Technology Corp. - * Contact: carrier <at> sleuthkit <dot> org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sleuthkit.datamodel.databaseutils; - -/** - * - */ -public class PostgreSQLQueryHelper implements DatabaseQueryHelper { - - @Override - public String getPrimaryKey() { - return "BIGSERIAL"; - } - - @Override - public String getBigIntType() { - return "BIGINT"; - } - - @Override - public String getBlobType() { - return "BYTEA"; - } - - @Override - public String getVSDescColName() { - return "descr"; - } -} diff --git a/bindings/java/src/org/sleuthkit/datamodel/databaseutils/SQLiteQueryHelper.java b/bindings/java/src/org/sleuthkit/datamodel/databaseutils/SQLiteQueryHelper.java deleted file mode 100644 index 05c5ea87da97457d60da7e3587b6734d1d470b26..0000000000000000000000000000000000000000 --- a/bindings/java/src/org/sleuthkit/datamodel/databaseutils/SQLiteQueryHelper.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Sleuth Kit Data Model - * - * Copyright 2020 Basis Technology Corp. - * Contact: carrier <at> sleuthkit <dot> org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sleuthkit.datamodel.databaseutils; - -/** - * - */ -public class SQLiteQueryHelper implements DatabaseQueryHelper { - - @Override - public String getPrimaryKey() { - return "INTEGER"; - } - - @Override - public String getBigIntType() { - return "INTEGER"; - } - - @Override - public String getBlobType() { - return "BLOB"; - } - - @Override - public String getVSDescColName() { - return "desc"; - } - -}