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(
"Central repository database missing", 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(
"Central repository database missing", Bundle.SqliteEamDb_centralRepositoryDisabled_message());
199 if (connectionPool == null) {
200 setupConnectionPool(foreignKeys);
203 return connectionPool.getConnection();
204 }
catch (SQLException ex) {
205 throw new EamDbException(
"Error getting connection from connection pool.", 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);
822 public void processSelectClause(String selectClause, InstanceTableCallback instanceTableCallback)
throws EamDbException {
825 super.processSelectClause(selectClause, instanceTableCallback);
844 public boolean referenceSetExists(String referenceSetName, String version)
throws EamDbException {
847 return super.referenceSetExists(referenceSetName, version);
862 public boolean isArtifactKnownBadByReference(CorrelationAttributeInstance.Type aType, String value)
throws EamDbException, CorrelationAttributeNormalizationException {
865 return super.isArtifactKnownBadByReference(aType, value);
881 public EamOrganization newOrganization(EamOrganization eamOrg)
throws EamDbException {
883 acquireExclusiveLock();
884 return super.newOrganization(eamOrg);
886 releaseExclusiveLock();
898 public List<EamOrganization> getOrganizations() throws EamDbException {
901 return super.getOrganizations();
917 public EamOrganization getOrganizationByID(
int orgID)
throws EamDbException {
920 return super.getOrganizationByID(orgID);
927 public void updateOrganization(EamOrganization updatedOrganization)
throws EamDbException {
929 acquireExclusiveLock();
930 super.updateOrganization(updatedOrganization);
932 releaseExclusiveLock();
937 public void deleteOrganization(EamOrganization organizationToDelete)
throws EamDbException {
939 acquireExclusiveLock();
940 super.deleteOrganization(organizationToDelete);
942 releaseExclusiveLock();
956 public int newReferenceSet(EamGlobalSet eamGlobalSet)
throws EamDbException {
958 acquireExclusiveLock();
959 return super.newReferenceSet(eamGlobalSet);
961 releaseExclusiveLock();
975 public EamGlobalSet getReferenceSetByID(
int referenceSetID)
throws EamDbException {
978 return super.getReferenceSetByID(referenceSetID);
994 public List<EamGlobalSet> getAllReferenceSets(CorrelationAttributeInstance.Type correlationType) throws EamDbException {
997 return super.getAllReferenceSets(correlationType);
1013 public void addReferenceInstance(EamGlobalFileInstance eamGlobalFileInstance, CorrelationAttributeInstance.Type correlationType) throws EamDbException {
1015 acquireExclusiveLock();
1016 super.addReferenceInstance(eamGlobalFileInstance, correlationType);
1018 releaseExclusiveLock();
1028 public void bulkInsertReferenceTypeEntries(Set<EamGlobalFileInstance> globalInstances, CorrelationAttributeInstance.Type contentType) throws EamDbException {
1030 acquireExclusiveLock();
1031 super.bulkInsertReferenceTypeEntries(globalInstances, contentType);
1033 releaseExclusiveLock();
1048 public List<EamGlobalFileInstance> getReferenceInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String aValue)
throws EamDbException, CorrelationAttributeNormalizationException {
1050 acquireSharedLock();
1051 return super.getReferenceInstancesByTypeValue(aType, aValue);
1053 releaseSharedLock();
1067 public int newCorrelationType(CorrelationAttributeInstance.Type newType) throws EamDbException {
1069 acquireExclusiveLock();
1070 return super.newCorrelationType(newType);
1072 releaseExclusiveLock();
1086 public List<CorrelationAttributeInstance.Type> getDefinedCorrelationTypes() throws EamDbException {
1088 acquireSharedLock();
1089 return super.getDefinedCorrelationTypes();
1091 releaseSharedLock();
1105 public List<CorrelationAttributeInstance.Type> getEnabledCorrelationTypes() throws EamDbException {
1107 acquireSharedLock();
1108 return super.getEnabledCorrelationTypes();
1110 releaseSharedLock();
1124 public List<CorrelationAttributeInstance.Type> getSupportedCorrelationTypes() throws EamDbException {
1126 acquireSharedLock();
1127 return super.getSupportedCorrelationTypes();
1129 releaseSharedLock();
1141 public void updateCorrelationType(CorrelationAttributeInstance.Type aType) throws EamDbException {
1143 acquireExclusiveLock();
1144 super.updateCorrelationType(aType);
1146 releaseExclusiveLock();
1160 public CorrelationAttributeInstance.Type getCorrelationTypeById(
int typeId)
throws EamDbException {
1162 acquireSharedLock();
1163 return super.getCorrelationTypeById(typeId);
1165 releaseSharedLock();
1175 public void upgradeSchema() throws EamDbException, SQLException, IncompatibleCentralRepoException {
1177 acquireExclusiveLock();
1178 super.upgradeSchema();
1180 releaseExclusiveLock();
1196 public CoordinationService.Lock getExclusiveMultiUserDbLock() throws EamDbException {
1206 private void acquireExclusiveLock() {
1207 rwLock.writeLock().lock();
1215 private void releaseExclusiveLock() {
1216 rwLock.writeLock().unlock();
1224 private void acquireSharedLock() {
1225 rwLock.readLock().lock();
1233 private void releaseSharedLock() {
1234 rwLock.readLock().unlock();
1238 boolean doesColumnExist(Connection conn, String tableName, String columnName)
throws SQLException {
1239 final String tableInfoQueryTemplate =
"PRAGMA table_info(%s)";
1240 ResultSet resultSet = null;
1241 Statement statement = null;
1242 boolean columnExists =
false;
1244 statement = conn.createStatement();
1245 resultSet = statement.executeQuery(String.format(tableInfoQueryTemplate, tableName));
1246 while (resultSet.next()) {
1248 if (resultSet.getString(2).equals(columnName)) {
1249 columnExists =
true;
1254 EamDbUtil.closeResultSet(resultSet);
1255 EamDbUtil.closeStatement(statement);
1257 return columnExists;