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);
849 public boolean referenceSetExists(String referenceSetName, String version)
throws CentralRepoException {
852 return super.referenceSetExists(referenceSetName, version);
867 public boolean isArtifactKnownBadByReference(CorrelationAttributeInstance.Type aType, String value)
throws CentralRepoException, CorrelationAttributeNormalizationException {
870 return super.isArtifactKnownBadByReference(aType, value);
886 public CentralRepoOrganization newOrganization(CentralRepoOrganization eamOrg)
throws CentralRepoException {
888 acquireExclusiveLock();
889 return super.newOrganization(eamOrg);
891 releaseExclusiveLock();
903 public List<CentralRepoOrganization> getOrganizations() throws CentralRepoException {
906 return super.getOrganizations();
922 public CentralRepoOrganization getOrganizationByID(
int orgID)
throws CentralRepoException {
925 return super.getOrganizationByID(orgID);
932 public void updateOrganization(CentralRepoOrganization updatedOrganization)
throws CentralRepoException {
934 acquireExclusiveLock();
935 super.updateOrganization(updatedOrganization);
937 releaseExclusiveLock();
942 public void deleteOrganization(CentralRepoOrganization organizationToDelete)
throws CentralRepoException {
944 acquireExclusiveLock();
945 super.deleteOrganization(organizationToDelete);
947 releaseExclusiveLock();
961 public int newReferenceSet(CentralRepoFileSet eamGlobalSet)
throws CentralRepoException {
963 acquireExclusiveLock();
964 return super.newReferenceSet(eamGlobalSet);
966 releaseExclusiveLock();
980 public CentralRepoFileSet getReferenceSetByID(
int referenceSetID)
throws CentralRepoException {
983 return super.getReferenceSetByID(referenceSetID);
999 public List<CentralRepoFileSet> getAllReferenceSets(CorrelationAttributeInstance.Type correlationType) throws CentralRepoException {
1001 acquireSharedLock();
1002 return super.getAllReferenceSets(correlationType);
1004 releaseSharedLock();
1018 public void addReferenceInstance(CentralRepoFileInstance eamGlobalFileInstance, CorrelationAttributeInstance.Type correlationType) throws CentralRepoException {
1020 acquireExclusiveLock();
1021 super.addReferenceInstance(eamGlobalFileInstance, correlationType);
1023 releaseExclusiveLock();
1033 public void bulkInsertReferenceTypeEntries(Set<CentralRepoFileInstance> globalInstances, CorrelationAttributeInstance.Type contentType) throws CentralRepoException {
1035 acquireExclusiveLock();
1036 super.bulkInsertReferenceTypeEntries(globalInstances, contentType);
1038 releaseExclusiveLock();
1053 public List<CentralRepoFileInstance> getReferenceInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String aValue)
throws CentralRepoException, CorrelationAttributeNormalizationException {
1055 acquireSharedLock();
1056 return super.getReferenceInstancesByTypeValue(aType, aValue);
1058 releaseSharedLock();
1072 public int newCorrelationType(CorrelationAttributeInstance.Type newType) throws CentralRepoException {
1074 acquireExclusiveLock();
1075 return super.newCorrelationType(newType);
1077 releaseExclusiveLock();
1091 public List<CorrelationAttributeInstance.Type> getDefinedCorrelationTypes() throws CentralRepoException {
1093 acquireSharedLock();
1094 return super.getDefinedCorrelationTypes();
1096 releaseSharedLock();
1110 public List<CorrelationAttributeInstance.Type> getEnabledCorrelationTypes() throws CentralRepoException {
1112 acquireSharedLock();
1113 return super.getEnabledCorrelationTypes();
1115 releaseSharedLock();
1129 public List<CorrelationAttributeInstance.Type> getSupportedCorrelationTypes() throws CentralRepoException {
1131 acquireSharedLock();
1132 return super.getSupportedCorrelationTypes();
1134 releaseSharedLock();
1146 public void updateCorrelationType(CorrelationAttributeInstance.Type aType) throws CentralRepoException {
1148 acquireExclusiveLock();
1149 super.updateCorrelationType(aType);
1151 releaseExclusiveLock();
1165 public CorrelationAttributeInstance.Type getCorrelationTypeById(
int typeId)
throws CentralRepoException {
1167 acquireSharedLock();
1168 return super.getCorrelationTypeById(typeId);
1170 releaseSharedLock();
1180 public void upgradeSchema() throws CentralRepoException, SQLException, IncompatibleCentralRepoException {
1182 acquireExclusiveLock();
1183 super.upgradeSchema();
1185 releaseExclusiveLock();
1201 public CoordinationService.Lock getExclusiveMultiUserDbLock() throws CentralRepoException {
1211 private void acquireExclusiveLock() {
1212 rwLock.writeLock().lock();
1220 private void releaseExclusiveLock() {
1221 rwLock.writeLock().unlock();
1229 private void acquireSharedLock() {
1230 rwLock.readLock().lock();
1238 private void releaseSharedLock() {
1239 rwLock.readLock().unlock();
1243 boolean doesColumnExist(Connection conn, String tableName, String columnName)
throws SQLException {
1244 final String tableInfoQueryTemplate =
"PRAGMA table_info(%s)";
1245 ResultSet resultSet = null;
1246 Statement statement = null;
1247 boolean columnExists =
false;
1249 statement = conn.createStatement();
1250 resultSet = statement.executeQuery(String.format(tableInfoQueryTemplate, tableName));
1251 while (resultSet.next()) {
1253 if (resultSet.getString(2).equals(columnName)) {
1254 columnExists =
true;
1259 CentralRepoDbUtil.closeResultSet(resultSet);
1260 CentralRepoDbUtil.closeStatement(statement);
1262 return columnExists;