19 package org.sleuthkit.autopsy.centralrepository.datamodel;
21 import java.sql.Connection;
22 import java.sql.ResultSet;
23 import java.sql.SQLException;
24 import java.sql.Statement;
25 import java.util.Arrays;
26 import java.util.List;
28 import java.util.concurrent.locks.ReentrantReadWriteLock;
29 import java.util.logging.Level;
30 import org.apache.commons.dbcp2.BasicDataSource;
31 import org.openide.util.NbBundle.Messages;
42 final class SqliteCentralRepo
extends RdbmsCentralRepo {
44 private final static Logger LOGGER = Logger.getLogger(SqliteCentralRepo.class.getName());
46 private static SqliteCentralRepo instance;
48 private BasicDataSource connectionPool = null;
50 private final SqliteCentralRepoSettings dbSettings;
54 private final ReentrantReadWriteLock rwLock =
new ReentrantReadWriteLock(
true);
64 public synchronized static SqliteCentralRepo getInstance() throws CentralRepoException {
65 if (instance == null) {
66 instance =
new SqliteCentralRepo();
78 private SqliteCentralRepo() throws CentralRepoException {
79 dbSettings =
new SqliteCentralRepoSettings();
80 bulkArtifactsThreshold = dbSettings.getBulkThreshold();
84 public void shutdownConnections() throws CentralRepoException {
87 if (null != connectionPool) {
88 connectionPool.close();
89 connectionPool = null;
93 }
catch (SQLException ex) {
94 throw new CentralRepoException(
"Failed to close existing database connections.", ex);
99 public void updateSettings() {
100 synchronized (
this) {
101 dbSettings.loadSettings();
102 bulkArtifactsThreshold = dbSettings.getBulkThreshold();
107 public void saveSettings() {
108 synchronized (
this) {
109 dbSettings.saveSettings();
114 public void reset() throws CentralRepoException {
116 acquireExclusiveLock();
118 Connection conn = connect();
122 Statement dropContent = conn.createStatement();
123 dropContent.executeUpdate(
"DELETE FROM organizations");
124 dropContent.executeUpdate(
"DELETE FROM cases");
125 dropContent.executeUpdate(
"DELETE FROM data_sources");
126 dropContent.executeUpdate(
"DELETE FROM reference_sets");
127 dropContent.executeUpdate(
"DELETE FROM artifact_types");
128 dropContent.executeUpdate(
"DELETE FROM db_info");
130 String instancesTemplate =
"DELETE FROM %s_instances";
131 String referencesTemplate =
"DELETE FROM global_files";
132 for (CorrelationAttributeInstance.Type type : defaultCorrelationTypes) {
133 dropContent.executeUpdate(String.format(instancesTemplate, type.getDbTableName()));
135 if (type.getId() == CorrelationAttributeInstance.FILES_TYPE_ID) {
136 dropContent.executeUpdate(String.format(referencesTemplate, type.getDbTableName()));
140 dropContent.executeUpdate(
"VACUUM");
141 }
catch (SQLException ex) {
142 LOGGER.log(Level.WARNING,
"Failed to reset database.", ex);
144 CentralRepoDbUtil.closeConnection(conn);
147 RdbmsCentralRepoFactory centralRepoSchemaFactory =
new RdbmsCentralRepoFactory(CentralRepoPlatforms.SQLITE, dbSettings);
148 centralRepoSchemaFactory.insertDefaultDatabaseContent();
150 releaseExclusiveLock();
158 @Messages({
"SqliteEamDb.databaseMissing.message=Central repository database missing"})
159 private void setupConnectionPool(
boolean foreignKeysEnabled)
throws CentralRepoException {
161 if (dbSettings.dbFileExists() ==
false) {
162 throw new CentralRepoException(
"Central repository database missing", Bundle.SqliteEamDb_databaseMissing_message());
165 connectionPool =
new BasicDataSource();
166 connectionPool.setDriverClassName(dbSettings.getDriver());
167 connectionPool.setUrl(dbSettings.getConnectionURL());
170 connectionPool.setInitialSize(50);
171 connectionPool.setMaxTotal(-1);
172 connectionPool.setMaxIdle(-1);
173 connectionPool.setMaxWaitMillis(1000);
174 connectionPool.setValidationQuery(dbSettings.getValidationQuery());
175 if (foreignKeysEnabled) {
176 connectionPool.setConnectionInitSqls(Arrays.asList(
"PRAGMA foreign_keys = ON"));
178 connectionPool.setConnectionInitSqls(Arrays.asList(
"PRAGMA foreign_keys = OFF"));
192 @Messages({
"SqliteEamDb.connectionFailedMessage.message=Error getting connection to database.",
193 "SqliteEamDb.centralRepositoryDisabled.message=Central Repository module is not enabled."})
195 protected Connection connect(
boolean foreignKeys)
throws CentralRepoException {
196 synchronized (
this) {
197 if (!CentralRepository.isEnabled()) {
198 throw new CentralRepoException(
"Central repository database missing", Bundle.SqliteEamDb_centralRepositoryDisabled_message());
200 if (connectionPool == null) {
201 setupConnectionPool(foreignKeys);
204 return connectionPool.getConnection();
205 }
catch (SQLException ex) {
206 throw new CentralRepoException(
"Error getting connection from connection pool.", Bundle.SqliteEamDb_connectionFailedMessage_message(), ex);
220 protected Connection connect() throws CentralRepoException {
221 return connect(
true);
225 protected String getConflictClause() {
231 protected Connection getEphemeralConnection() {
232 return this.dbSettings.getEphemeralConnection();
243 public void newDbInfo(String name, String value)
throws CentralRepoException {
245 acquireExclusiveLock();
246 super.newDbInfo(name, value);
248 releaseExclusiveLock();
262 public String getDbInfo(String name)
throws CentralRepoException {
265 return super.getDbInfo(name);
280 public void updateDbInfo(String name, String value)
throws CentralRepoException {
282 acquireExclusiveLock();
283 super.updateDbInfo(name, value);
285 releaseExclusiveLock();
295 public CorrelationCase newCase(Case autopsyCase)
throws CentralRepoException {
297 acquireExclusiveLock();
298 return super.newCase(autopsyCase);
300 releaseExclusiveLock();
305 public void addDataSourceObjectId(
int rowId,
long dataSourceObjectId)
throws CentralRepoException {
307 acquireExclusiveLock();
308 super.addDataSourceObjectId(rowId, dataSourceObjectId);
310 releaseExclusiveLock();
322 public CorrelationCase newCase(CorrelationCase eamCase)
throws CentralRepoException {
324 acquireExclusiveLock();
325 return super.newCase(eamCase);
327 releaseExclusiveLock();
337 public void updateCase(CorrelationCase eamCase)
throws CentralRepoException {
339 acquireExclusiveLock();
340 super.updateCase(eamCase);
342 releaseExclusiveLock();
354 public CorrelationCase getCaseByUUID(String caseUUID)
throws CentralRepoException {
357 return super.getCaseByUUID(caseUUID);
371 public CorrelationCase getCaseById(
int caseId)
throws CentralRepoException {
374 return super.getCaseById(caseId);
387 public List<CorrelationCase> getCases() throws CentralRepoException {
390 return super.getCases();
402 public CorrelationDataSource newDataSource(CorrelationDataSource eamDataSource)
throws CentralRepoException {
404 acquireExclusiveLock();
405 return super.newDataSource(eamDataSource);
407 releaseExclusiveLock();
421 public CorrelationDataSource getDataSource(CorrelationCase correlationCase, Long caseDbDataSourceId)
throws CentralRepoException {
424 return super.getDataSource(correlationCase, caseDbDataSourceId);
440 public CorrelationDataSource getDataSourceById(CorrelationCase correlationCase,
int dataSourceId)
throws CentralRepoException {
443 return super.getDataSourceById(correlationCase, dataSourceId);
455 public List<CorrelationDataSource> getDataSources() throws CentralRepoException {
458 return super.getDataSources();
473 public void updateDataSourceName(CorrelationDataSource eamDataSource, String newName)
throws CentralRepoException {
475 acquireExclusiveLock();
476 super.updateDataSourceName(eamDataSource, newName);
478 releaseExclusiveLock();
488 public void updateDataSourceMd5Hash(CorrelationDataSource eamDataSource)
throws CentralRepoException {
490 acquireExclusiveLock();
491 super.updateDataSourceMd5Hash(eamDataSource);
493 releaseExclusiveLock();
503 public void updateDataSourceSha1Hash(CorrelationDataSource eamDataSource)
throws CentralRepoException {
505 acquireExclusiveLock();
506 super.updateDataSourceSha1Hash(eamDataSource);
508 releaseExclusiveLock();
519 public void updateDataSourceSha256Hash(CorrelationDataSource eamDataSource)
throws CentralRepoException {
521 acquireExclusiveLock();
522 super.updateDataSourceSha256Hash(eamDataSource);
524 releaseExclusiveLock();
535 public void addArtifactInstance(CorrelationAttributeInstance eamArtifact)
throws CentralRepoException {
537 acquireExclusiveLock();
538 super.addArtifactInstance(eamArtifact);
540 releaseExclusiveLock();
545 public List<CorrelationAttributeInstance> getArtifactInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String value)
throws CentralRepoException, CorrelationAttributeNormalizationException {
548 return super.getArtifactInstancesByTypeValue(aType, value);
555 public List<CorrelationAttributeInstance> getArtifactInstancesByTypeValues(CorrelationAttributeInstance.Type aType, List<String> values)
throws CentralRepoException, CorrelationAttributeNormalizationException {
558 return super.getArtifactInstancesByTypeValues(aType, values);
565 public List<CorrelationAttributeInstance> getArtifactInstancesByTypeValuesAndCases(CorrelationAttributeInstance.Type aType, List<String> values, List<Integer> caseIds)
throws CentralRepoException, CorrelationAttributeNormalizationException {
568 return super.getArtifactInstancesByTypeValuesAndCases(aType, values, caseIds);
587 public Long getCountArtifactInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String value)
throws CentralRepoException, CorrelationAttributeNormalizationException {
590 return super.getCountArtifactInstancesByTypeValue(aType, value);
597 public int getFrequencyPercentage(CorrelationAttributeInstance corAttr)
throws CentralRepoException, CorrelationAttributeNormalizationException {
600 return super.getFrequencyPercentage(corAttr);
619 public Long getCountUniqueCaseDataSourceTuplesHavingTypeValue(CorrelationAttributeInstance.Type aType, String value)
throws CentralRepoException, CorrelationAttributeNormalizationException {
622 return super.getCountUniqueCaseDataSourceTuplesHavingTypeValue(aType, value);
629 public Long getCountUniqueDataSources() throws CentralRepoException {
632 return super.getCountUniqueDataSources();
650 public Long getCountArtifactInstancesByCaseDataSource(CorrelationDataSource correlationDataSource)
throws CentralRepoException {
653 return super.getCountArtifactInstancesByCaseDataSource(correlationDataSource);
664 public void commitAttributeInstancesBulk() throws CentralRepoException {
666 acquireExclusiveLock();
667 super.commitAttributeInstancesBulk();
669 releaseExclusiveLock();
677 public void bulkInsertCases(List<CorrelationCase> cases)
throws CentralRepoException {
679 acquireExclusiveLock();
680 super.bulkInsertCases(cases);
682 releaseExclusiveLock();
697 public void setAttributeInstanceKnownStatus(CorrelationAttributeInstance eamArtifact, TskData.FileKnown knownStatus) throws CentralRepoException {
699 acquireExclusiveLock();
700 super.setAttributeInstanceKnownStatus(eamArtifact, knownStatus);
702 releaseExclusiveLock();
715 public Long getCountArtifactInstancesKnownBad(CorrelationAttributeInstance.Type aType, String value)
throws CentralRepoException, CorrelationAttributeNormalizationException {
718 return super.getCountArtifactInstancesKnownBad(aType, value);
737 public List<String> getListCasesHavingArtifactInstancesKnownBad(CorrelationAttributeInstance.Type aType, String value)
throws CentralRepoException, CorrelationAttributeNormalizationException {
740 return super.getListCasesHavingArtifactInstancesKnownBad(aType, value);
754 public void deleteReferenceSet(
int referenceSetID)
throws CentralRepoException {
756 acquireExclusiveLock();
757 super.deleteReferenceSet(referenceSetID);
759 releaseExclusiveLock();
773 public boolean isValueInReferenceSet(String value,
int referenceSetID,
int correlationTypeID)
throws CentralRepoException, CorrelationAttributeNormalizationException {
776 return super.isValueInReferenceSet(value, referenceSetID, correlationTypeID);
791 public void processInstanceTable(CorrelationAttributeInstance.Type type, InstanceTableCallback instanceTableCallback)
throws CentralRepoException {
794 super.processInstanceTable(type, instanceTableCallback);
809 public void processInstanceTableWhere(CorrelationAttributeInstance.Type type, String whereClause, InstanceTableCallback instanceTableCallback)
throws CentralRepoException {
812 super.processInstanceTableWhere(type, whereClause, instanceTableCallback);
827 public void processSelectClause(String selectClause, InstanceTableCallback instanceTableCallback)
throws CentralRepoException {
830 super.processSelectClause(selectClause, instanceTableCallback);
837 public void executeCommand(String sql, List<Object> params)
throws CentralRepoException {
839 acquireExclusiveLock();
840 super.executeCommand(sql, params);
842 releaseExclusiveLock();
847 public void executeQuery(String sql, List<Object> params, CentralRepositoryDbQueryCallback queryCallback)
throws CentralRepoException {
850 super.executeQuery(sql, params, queryCallback);
869 public boolean referenceSetExists(String referenceSetName, String version)
throws CentralRepoException {
872 return super.referenceSetExists(referenceSetName, version);
887 public boolean isArtifactKnownBadByReference(CorrelationAttributeInstance.Type aType, String value)
throws CentralRepoException, CorrelationAttributeNormalizationException {
890 return super.isArtifactKnownBadByReference(aType, value);
906 public CentralRepoOrganization newOrganization(CentralRepoOrganization eamOrg)
throws CentralRepoException {
908 acquireExclusiveLock();
909 return super.newOrganization(eamOrg);
911 releaseExclusiveLock();
923 public List<CentralRepoOrganization> getOrganizations() throws CentralRepoException {
926 return super.getOrganizations();
942 public CentralRepoOrganization getOrganizationByID(
int orgID)
throws CentralRepoException {
945 return super.getOrganizationByID(orgID);
952 public void updateOrganization(CentralRepoOrganization updatedOrganization)
throws CentralRepoException {
954 acquireExclusiveLock();
955 super.updateOrganization(updatedOrganization);
957 releaseExclusiveLock();
962 public void deleteOrganization(CentralRepoOrganization organizationToDelete)
throws CentralRepoException {
964 acquireExclusiveLock();
965 super.deleteOrganization(organizationToDelete);
967 releaseExclusiveLock();
981 public int newReferenceSet(CentralRepoFileSet eamGlobalSet)
throws CentralRepoException {
983 acquireExclusiveLock();
984 return super.newReferenceSet(eamGlobalSet);
986 releaseExclusiveLock();
1000 public CentralRepoFileSet getReferenceSetByID(
int referenceSetID)
throws CentralRepoException {
1002 acquireSharedLock();
1003 return super.getReferenceSetByID(referenceSetID);
1005 releaseSharedLock();
1019 public List<CentralRepoFileSet> getAllReferenceSets(CorrelationAttributeInstance.Type correlationType) throws CentralRepoException {
1021 acquireSharedLock();
1022 return super.getAllReferenceSets(correlationType);
1024 releaseSharedLock();
1038 public void addReferenceInstance(CentralRepoFileInstance eamGlobalFileInstance, CorrelationAttributeInstance.Type correlationType) throws CentralRepoException {
1040 acquireExclusiveLock();
1041 super.addReferenceInstance(eamGlobalFileInstance, correlationType);
1043 releaseExclusiveLock();
1053 public void bulkInsertReferenceTypeEntries(Set<CentralRepoFileInstance> globalInstances, CorrelationAttributeInstance.Type contentType) throws CentralRepoException {
1055 acquireExclusiveLock();
1056 super.bulkInsertReferenceTypeEntries(globalInstances, contentType);
1058 releaseExclusiveLock();
1073 public List<CentralRepoFileInstance> getReferenceInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String aValue)
throws CentralRepoException, CorrelationAttributeNormalizationException {
1075 acquireSharedLock();
1076 return super.getReferenceInstancesByTypeValue(aType, aValue);
1078 releaseSharedLock();
1092 public int newCorrelationType(CorrelationAttributeInstance.Type newType) throws CentralRepoException {
1094 acquireExclusiveLock();
1095 return super.newCorrelationType(newType);
1097 releaseExclusiveLock();
1111 public List<CorrelationAttributeInstance.Type> getDefinedCorrelationTypes() throws CentralRepoException {
1113 acquireSharedLock();
1114 return super.getDefinedCorrelationTypes();
1116 releaseSharedLock();
1130 public List<CorrelationAttributeInstance.Type> getEnabledCorrelationTypes() throws CentralRepoException {
1132 acquireSharedLock();
1133 return super.getEnabledCorrelationTypes();
1135 releaseSharedLock();
1149 public List<CorrelationAttributeInstance.Type> getSupportedCorrelationTypes() throws CentralRepoException {
1151 acquireSharedLock();
1152 return super.getSupportedCorrelationTypes();
1154 releaseSharedLock();
1166 public void updateCorrelationType(CorrelationAttributeInstance.Type aType) throws CentralRepoException {
1168 acquireExclusiveLock();
1169 super.updateCorrelationType(aType);
1171 releaseExclusiveLock();
1185 public CorrelationAttributeInstance.Type getCorrelationTypeById(
int typeId)
throws CentralRepoException {
1187 acquireSharedLock();
1188 return super.getCorrelationTypeById(typeId);
1190 releaseSharedLock();
1200 public void upgradeSchema() throws CentralRepoException, SQLException, IncompatibleCentralRepoException {
1202 acquireExclusiveLock();
1203 super.upgradeSchema();
1205 releaseExclusiveLock();
1221 public CoordinationService.Lock getExclusiveMultiUserDbLock() throws CentralRepoException {
1231 private void acquireExclusiveLock() {
1232 rwLock.writeLock().lock();
1240 private void releaseExclusiveLock() {
1241 rwLock.writeLock().unlock();
1249 private void acquireSharedLock() {
1250 rwLock.readLock().lock();
1258 private void releaseSharedLock() {
1259 rwLock.readLock().unlock();
1263 boolean doesColumnExist(Connection conn, String tableName, String columnName)
throws SQLException {
1264 final String tableInfoQueryTemplate =
"PRAGMA table_info(%s)";
1265 ResultSet resultSet = null;
1266 Statement statement = null;
1267 boolean columnExists =
false;
1269 statement = conn.createStatement();
1270 resultSet = statement.executeQuery(String.format(tableInfoQueryTemplate, tableName));
1271 while (resultSet.next()) {
1273 if (resultSet.getString(2).equals(columnName)) {
1274 columnExists =
true;
1279 CentralRepoDbUtil.closeResultSet(resultSet);
1280 CentralRepoDbUtil.closeStatement(statement);
1282 return columnExists;