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 SqliteEamDb
extends AbstractSqlEamDb {
44 private final static Logger LOGGER = Logger.getLogger(SqliteEamDb.class.getName());
46 private static SqliteEamDb instance;
48 private BasicDataSource connectionPool = null;
50 private final SqliteEamDbSettings dbSettings;
54 private final ReentrantReadWriteLock rwLock =
new ReentrantReadWriteLock(
true);
64 public synchronized static SqliteEamDb getInstance() throws EamDbException {
65 if (instance == null) {
66 instance =
new SqliteEamDb();
78 private SqliteEamDb() throws EamDbException {
79 dbSettings =
new SqliteEamDbSettings();
80 bulkArtifactsThreshold = dbSettings.getBulkThreshold();
84 public void shutdownConnections() throws EamDbException {
87 if (null != connectionPool) {
88 connectionPool.close();
89 connectionPool = null;
93 }
catch (SQLException ex) {
94 throw new EamDbException(
"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 EamDbException {
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 EamDbUtil.closeConnection(conn);
147 dbSettings.insertDefaultDatabaseContent();
149 releaseExclusiveLock();
157 @Messages({
"SqliteEamDb.databaseMissing.message=Central repository database missing"})
158 private void setupConnectionPool(
boolean foreignKeysEnabled)
throws EamDbException {
160 if (dbSettings.dbFileExists() ==
false) {
161 throw new EamDbException(Bundle.SqliteEamDb_databaseMissing_message());
164 connectionPool =
new BasicDataSource();
165 connectionPool.setDriverClassName(dbSettings.getDriver());
166 connectionPool.setUrl(dbSettings.getConnectionURL());
169 connectionPool.setInitialSize(50);
170 connectionPool.setMaxTotal(-1);
171 connectionPool.setMaxIdle(-1);
172 connectionPool.setMaxWaitMillis(1000);
173 connectionPool.setValidationQuery(dbSettings.getValidationQuery());
174 if (foreignKeysEnabled) {
175 connectionPool.setConnectionInitSqls(Arrays.asList(
"PRAGMA foreign_keys = ON"));
177 connectionPool.setConnectionInitSqls(Arrays.asList(
"PRAGMA foreign_keys = OFF"));
191 @Messages({
"SqliteEamDb.connectionFailedMessage.message=Error getting connection to database.",
192 "SqliteEamDb.centralRepositoryDisabled.message=Central Repository module is not enabled."})
194 protected Connection connect(
boolean foreignKeys)
throws EamDbException {
195 synchronized (
this) {
196 if (!EamDb.isEnabled()) {
197 throw new EamDbException(Bundle.SqliteEamDb_centralRepositoryDisabled_message());
199 if (connectionPool == null) {
200 setupConnectionPool(foreignKeys);
203 return connectionPool.getConnection();
204 }
catch (SQLException ex) {
205 throw new EamDbException(Bundle.SqliteEamDb_connectionFailedMessage_message(), ex);
219 protected Connection connect() throws EamDbException {
220 return connect(
true);
224 protected String getConflictClause() {
238 public void newDbInfo(String name, String value)
throws EamDbException {
240 acquireExclusiveLock();
241 super.newDbInfo(name, value);
243 releaseExclusiveLock();
257 public String getDbInfo(String name)
throws EamDbException {
260 return super.getDbInfo(name);
275 public void updateDbInfo(String name, String value)
throws EamDbException {
277 acquireExclusiveLock();
278 super.updateDbInfo(name, value);
280 releaseExclusiveLock();
290 public CorrelationCase newCase(Case autopsyCase)
throws EamDbException {
292 acquireExclusiveLock();
293 return super.newCase(autopsyCase);
295 releaseExclusiveLock();
300 public void addDataSourceObjectId(
int rowId,
long dataSourceObjectId)
throws EamDbException {
302 acquireExclusiveLock();
303 super.addDataSourceObjectId(rowId, dataSourceObjectId);
305 releaseExclusiveLock();
317 public CorrelationCase newCase(CorrelationCase eamCase)
throws EamDbException {
319 acquireExclusiveLock();
320 return super.newCase(eamCase);
322 releaseExclusiveLock();
332 public void updateCase(CorrelationCase eamCase)
throws EamDbException {
334 acquireExclusiveLock();
335 super.updateCase(eamCase);
337 releaseExclusiveLock();
349 public CorrelationCase getCaseByUUID(String caseUUID)
throws EamDbException {
352 return super.getCaseByUUID(caseUUID);
366 public CorrelationCase getCaseById(
int caseId)
throws EamDbException {
369 return super.getCaseById(caseId);
382 public List<CorrelationCase> getCases() throws EamDbException {
385 return super.getCases();
397 public CorrelationDataSource newDataSource(CorrelationDataSource eamDataSource)
throws EamDbException {
399 acquireExclusiveLock();
400 return super.newDataSource(eamDataSource);
402 releaseExclusiveLock();
416 public CorrelationDataSource getDataSource(CorrelationCase correlationCase, Long caseDbDataSourceId)
throws EamDbException {
419 return super.getDataSource(correlationCase, caseDbDataSourceId);
435 public CorrelationDataSource getDataSourceById(CorrelationCase correlationCase,
int dataSourceId)
throws EamDbException {
438 return super.getDataSourceById(correlationCase, dataSourceId);
450 public List<CorrelationDataSource> getDataSources() throws EamDbException {
453 return super.getDataSources();
468 public void updateDataSourceName(CorrelationDataSource eamDataSource, String newName)
throws EamDbException {
470 acquireExclusiveLock();
471 super.updateDataSourceName(eamDataSource, newName);
473 releaseExclusiveLock();
483 public void updateDataSourceMd5Hash(CorrelationDataSource eamDataSource)
throws EamDbException {
485 acquireExclusiveLock();
486 super.updateDataSourceMd5Hash(eamDataSource);
488 releaseExclusiveLock();
498 public void updateDataSourceSha1Hash(CorrelationDataSource eamDataSource)
throws EamDbException {
500 acquireExclusiveLock();
501 super.updateDataSourceSha1Hash(eamDataSource);
503 releaseExclusiveLock();
514 public void updateDataSourceSha256Hash(CorrelationDataSource eamDataSource)
throws EamDbException {
516 acquireExclusiveLock();
517 super.updateDataSourceSha256Hash(eamDataSource);
519 releaseExclusiveLock();
530 public void addArtifactInstance(CorrelationAttributeInstance eamArtifact)
throws EamDbException {
532 acquireExclusiveLock();
533 super.addArtifactInstance(eamArtifact);
535 releaseExclusiveLock();
540 public List<CorrelationAttributeInstance> getArtifactInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String value)
throws EamDbException, CorrelationAttributeNormalizationException {
543 return super.getArtifactInstancesByTypeValue(aType, value);
550 public List<CorrelationAttributeInstance> getArtifactInstancesByTypeValues(CorrelationAttributeInstance.Type aType, List<String> values)
throws EamDbException, CorrelationAttributeNormalizationException {
553 return super.getArtifactInstancesByTypeValues(aType, values);
560 public List<CorrelationAttributeInstance> getArtifactInstancesByTypeValuesAndCases(CorrelationAttributeInstance.Type aType, List<String> values, List<Integer> caseIds)
throws EamDbException, CorrelationAttributeNormalizationException {
563 return super.getArtifactInstancesByTypeValuesAndCases(aType, values, caseIds);
582 public Long getCountArtifactInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String value)
throws EamDbException, CorrelationAttributeNormalizationException {
585 return super.getCountArtifactInstancesByTypeValue(aType, value);
592 public int getFrequencyPercentage(CorrelationAttributeInstance corAttr)
throws EamDbException, CorrelationAttributeNormalizationException {
595 return super.getFrequencyPercentage(corAttr);
614 public Long getCountUniqueCaseDataSourceTuplesHavingTypeValue(CorrelationAttributeInstance.Type aType, String value)
throws EamDbException, CorrelationAttributeNormalizationException {
617 return super.getCountUniqueCaseDataSourceTuplesHavingTypeValue(aType, value);
624 public Long getCountUniqueDataSources() throws EamDbException {
627 return super.getCountUniqueDataSources();
645 public Long getCountArtifactInstancesByCaseDataSource(CorrelationDataSource correlationDataSource)
throws EamDbException {
648 return super.getCountArtifactInstancesByCaseDataSource(correlationDataSource);
659 public void commitAttributeInstancesBulk() throws EamDbException {
661 acquireExclusiveLock();
662 super.commitAttributeInstancesBulk();
664 releaseExclusiveLock();
672 public void bulkInsertCases(List<CorrelationCase> cases)
throws EamDbException {
674 acquireExclusiveLock();
675 super.bulkInsertCases(cases);
677 releaseExclusiveLock();
692 public void setAttributeInstanceKnownStatus(CorrelationAttributeInstance eamArtifact, TskData.FileKnown knownStatus) throws EamDbException {
694 acquireExclusiveLock();
695 super.setAttributeInstanceKnownStatus(eamArtifact, knownStatus);
697 releaseExclusiveLock();
710 public Long getCountArtifactInstancesKnownBad(CorrelationAttributeInstance.Type aType, String value)
throws EamDbException, CorrelationAttributeNormalizationException {
713 return super.getCountArtifactInstancesKnownBad(aType, value);
732 public List<String> getListCasesHavingArtifactInstancesKnownBad(CorrelationAttributeInstance.Type aType, String value)
throws EamDbException, CorrelationAttributeNormalizationException {
735 return super.getListCasesHavingArtifactInstancesKnownBad(aType, value);
749 public void deleteReferenceSet(
int referenceSetID)
throws EamDbException {
751 acquireExclusiveLock();
752 super.deleteReferenceSet(referenceSetID);
754 releaseExclusiveLock();
768 public boolean isValueInReferenceSet(String value,
int referenceSetID,
int correlationTypeID)
throws EamDbException, CorrelationAttributeNormalizationException {
771 return super.isValueInReferenceSet(value, referenceSetID, correlationTypeID);
786 public void processInstanceTable(CorrelationAttributeInstance.Type type, InstanceTableCallback instanceTableCallback)
throws EamDbException {
789 super.processInstanceTable(type, instanceTableCallback);
804 public void processInstanceTableWhere(CorrelationAttributeInstance.Type type, String whereClause, InstanceTableCallback instanceTableCallback)
throws EamDbException {
807 super.processInstanceTableWhere(type, whereClause, instanceTableCallback);
826 public boolean referenceSetExists(String referenceSetName, String version)
throws EamDbException {
829 return super.referenceSetExists(referenceSetName, version);
844 public boolean isArtifactKnownBadByReference(CorrelationAttributeInstance.Type aType, String value)
throws EamDbException, CorrelationAttributeNormalizationException {
847 return super.isArtifactKnownBadByReference(aType, value);
863 public EamOrganization newOrganization(EamOrganization eamOrg)
throws EamDbException {
865 acquireExclusiveLock();
866 return super.newOrganization(eamOrg);
868 releaseExclusiveLock();
880 public List<EamOrganization> getOrganizations() throws EamDbException {
883 return super.getOrganizations();
899 public EamOrganization getOrganizationByID(
int orgID)
throws EamDbException {
902 return super.getOrganizationByID(orgID);
909 public void updateOrganization(EamOrganization updatedOrganization)
throws EamDbException {
911 acquireExclusiveLock();
912 super.updateOrganization(updatedOrganization);
914 releaseExclusiveLock();
919 public void deleteOrganization(EamOrganization organizationToDelete)
throws EamDbException {
921 acquireExclusiveLock();
922 super.deleteOrganization(organizationToDelete);
924 releaseExclusiveLock();
938 public int newReferenceSet(EamGlobalSet eamGlobalSet)
throws EamDbException {
940 acquireExclusiveLock();
941 return super.newReferenceSet(eamGlobalSet);
943 releaseExclusiveLock();
957 public EamGlobalSet getReferenceSetByID(
int referenceSetID)
throws EamDbException {
960 return super.getReferenceSetByID(referenceSetID);
976 public List<EamGlobalSet> getAllReferenceSets(CorrelationAttributeInstance.Type correlationType) throws EamDbException {
979 return super.getAllReferenceSets(correlationType);
995 public void addReferenceInstance(EamGlobalFileInstance eamGlobalFileInstance, CorrelationAttributeInstance.Type correlationType) throws EamDbException {
997 acquireExclusiveLock();
998 super.addReferenceInstance(eamGlobalFileInstance, correlationType);
1000 releaseExclusiveLock();
1010 public void bulkInsertReferenceTypeEntries(Set<EamGlobalFileInstance> globalInstances, CorrelationAttributeInstance.Type contentType) throws EamDbException {
1012 acquireExclusiveLock();
1013 super.bulkInsertReferenceTypeEntries(globalInstances, contentType);
1015 releaseExclusiveLock();
1030 public List<EamGlobalFileInstance> getReferenceInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String aValue)
throws EamDbException, CorrelationAttributeNormalizationException {
1032 acquireSharedLock();
1033 return super.getReferenceInstancesByTypeValue(aType, aValue);
1035 releaseSharedLock();
1049 public int newCorrelationType(CorrelationAttributeInstance.Type newType) throws EamDbException {
1051 acquireExclusiveLock();
1052 return super.newCorrelationType(newType);
1054 releaseExclusiveLock();
1068 public List<CorrelationAttributeInstance.Type> getDefinedCorrelationTypes() throws EamDbException {
1070 acquireSharedLock();
1071 return super.getDefinedCorrelationTypes();
1073 releaseSharedLock();
1087 public List<CorrelationAttributeInstance.Type> getEnabledCorrelationTypes() throws EamDbException {
1089 acquireSharedLock();
1090 return super.getEnabledCorrelationTypes();
1092 releaseSharedLock();
1106 public List<CorrelationAttributeInstance.Type> getSupportedCorrelationTypes() throws EamDbException {
1108 acquireSharedLock();
1109 return super.getSupportedCorrelationTypes();
1111 releaseSharedLock();
1123 public void updateCorrelationType(CorrelationAttributeInstance.Type aType) throws EamDbException {
1125 acquireExclusiveLock();
1126 super.updateCorrelationType(aType);
1128 releaseExclusiveLock();
1142 public CorrelationAttributeInstance.Type getCorrelationTypeById(
int typeId)
throws EamDbException {
1144 acquireSharedLock();
1145 return super.getCorrelationTypeById(typeId);
1147 releaseSharedLock();
1157 public void upgradeSchema() throws EamDbException, SQLException, IncompatibleCentralRepoException {
1159 acquireExclusiveLock();
1160 super.upgradeSchema();
1162 releaseExclusiveLock();
1178 public CoordinationService.Lock getExclusiveMultiUserDbLock() throws EamDbException {
1188 private void acquireExclusiveLock() {
1189 rwLock.writeLock().lock();
1197 private void releaseExclusiveLock() {
1198 rwLock.writeLock().unlock();
1206 private void acquireSharedLock() {
1207 rwLock.readLock().lock();
1215 private void releaseSharedLock() {
1216 rwLock.readLock().unlock();
1220 boolean doesColumnExist(Connection conn, String tableName, String columnName)
throws SQLException {
1221 final String tableInfoQueryTemplate =
"PRAGMA table_info(%s)";
1222 ResultSet resultSet = null;
1223 Statement statement = null;
1224 boolean columnExists =
false;
1226 statement = conn.createStatement();
1227 resultSet = statement.executeQuery(String.format(tableInfoQueryTemplate, tableName));
1228 while (resultSet.next()) {
1230 if (resultSet.getString(2).equals(columnName)) {
1231 columnExists =
true;
1236 EamDbUtil.closeResultSet(resultSet);
1237 EamDbUtil.closeStatement(statement);
1239 return columnExists;