Autopsy 4.22.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
PostgresCentralRepo.java
Go to the documentation of this file.
1/*
2 * Central Repository
3 *
4 * Copyright 2015-2018 Basis Technology Corp.
5 * Contact: carrier <at> sleuthkit <dot> org
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19package org.sleuthkit.autopsy.centralrepository.datamodel;
20
21import java.sql.Connection;
22import java.sql.ResultSet;
23import java.sql.SQLException;
24import java.sql.Statement;
25import java.util.concurrent.TimeUnit;
26import java.util.logging.Level;
27import org.apache.commons.dbcp2.BasicDataSource;
28import org.openide.util.NbBundle.Messages;
29import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
30import org.sleuthkit.autopsy.core.UserPreferences;
31import org.sleuthkit.autopsy.coreutils.Logger;
32
36final class PostgresCentralRepo extends RdbmsCentralRepo {
37
38 private final static Logger LOGGER = Logger.getLogger(PostgresCentralRepo.class.getName());
39
40 private final static String CONFLICT_CLAUSE = "ON CONFLICT DO NOTHING";
41
42 private static PostgresCentralRepo instance;
43
44 private static final int CONN_POOL_SIZE = 10;
45 private BasicDataSource connectionPool = null;
46
47 private final PostgresCentralRepoSettings dbSettings;
48
57 public synchronized static PostgresCentralRepo getInstance() throws CentralRepoException {
58 if (instance == null) {
59 instance = new PostgresCentralRepo();
60 }
61
62 return instance;
63 }
64
71 private PostgresCentralRepo() throws CentralRepoException {
72 dbSettings = new PostgresCentralRepoSettings();
73 bulkArtifactsThreshold = dbSettings.getBulkThreshold();
74 }
75
76 @Override
77 public void shutdownConnections() throws CentralRepoException {
78 try {
79 synchronized (this) {
80 if (connectionPool != null) {
81 connectionPool.close();
82 connectionPool = null; // force it to be re-created on next connect()
83 }
84 clearCaches();
85 }
86 } catch (SQLException ex) {
87 throw new CentralRepoException("Failed to close existing database connections.", ex); // NON-NLS
88 }
89 }
90
91 @Override
92 public void updateSettings() {
93 synchronized (this) {
94 dbSettings.loadSettings();
95 bulkArtifactsThreshold = dbSettings.getBulkThreshold();
96 }
97 }
98
99 @Override
100 public void saveSettings() {
101 synchronized (this) {
102 dbSettings.saveSettings();
103 }
104 }
105
106 @Override
107 public void reset() throws CentralRepoException {
108 Connection conn = connect();
109
110 try {
111 Statement dropContent = conn.createStatement();
112 dropContent.executeUpdate("TRUNCATE TABLE organizations RESTART IDENTITY CASCADE");
113 dropContent.executeUpdate("TRUNCATE TABLE cases RESTART IDENTITY CASCADE");
114 dropContent.executeUpdate("TRUNCATE TABLE data_sources RESTART IDENTITY CASCADE");
115 dropContent.executeUpdate("TRUNCATE TABLE reference_sets RESTART IDENTITY CASCADE");
116 dropContent.executeUpdate("TRUNCATE TABLE correlation_types RESTART IDENTITY CASCADE");
117 dropContent.executeUpdate("TRUNCATE TABLE db_info RESTART IDENTITY CASCADE");
118
119 String instancesTemplate = "TRUNCATE TABLE %s_instances RESTART IDENTITY CASCADE";
120 String referencesTemplate = "TRUNCATE TABLE reference_%s RESTART IDENTITY CASCADE";
121 for (CorrelationAttributeInstance.Type type : defaultCorrelationTypes) {
122 dropContent.executeUpdate(String.format(instancesTemplate, type.getDbTableName()));
123 // FUTURE: support other reference types
124 if (type.getId() == CorrelationAttributeInstance.FILES_TYPE_ID) {
125 dropContent.executeUpdate(String.format(referencesTemplate, type.getDbTableName()));
126 }
127 }
128 } catch (SQLException ex) {
129 LOGGER.log(Level.WARNING, "Failed to reset database.", ex);
130 } finally {
131 CentralRepoDbUtil.closeConnection(conn);
132 }
133
134
135 RdbmsCentralRepoFactory centralRepoSchemaFactory = new RdbmsCentralRepoFactory(CentralRepoPlatforms.POSTGRESQL, dbSettings);
136 centralRepoSchemaFactory.insertDefaultDatabaseContent();
137 }
138
143 private void setupConnectionPool() throws CentralRepoException {
144 connectionPool = new BasicDataSource();
145 connectionPool.setUsername(dbSettings.getUserName());
146 connectionPool.setPassword(dbSettings.getPassword());
147 connectionPool.setDriverClassName(dbSettings.getDriver());
148
149 StringBuilder connectionURL = new StringBuilder();
150 connectionURL.append(dbSettings.getJDBCBaseURI());
151 connectionURL.append(dbSettings.getHost());
152 connectionURL.append(":");
153 connectionURL.append(dbSettings.getPort());
154 connectionURL.append("/");
155 connectionURL.append(dbSettings.getDbName());
156
157 connectionPool.setUrl(connectionURL.toString());
158 connectionPool.setUsername(dbSettings.getUserName());
159 connectionPool.setPassword(dbSettings.getPassword());
160
161 // tweak pool configuration
162 connectionPool.setInitialSize(5); // start with 5 connections
163 connectionPool.setMaxIdle(CONN_POOL_SIZE); // max of 10 idle connections
164 connectionPool.setValidationQuery(dbSettings.getValidationQuery());
165 }
166
176 @Override
177 protected Connection connect(boolean foreignKeys) throws CentralRepoException {
178 //foreignKeys boolean is ignored for postgres
179 return connect();
180 }
181
189 @Messages({"PostgresEamDb.centralRepoDisabled.message=Central Repository module is not enabled.",
190 "PostgresEamDb.connectionFailed.message=Error getting connection to database."})
191 @Override
192 protected Connection connect() throws CentralRepoException {
193 synchronized (this) {
194 if (!CentralRepository.isEnabled()) {
195 throw new CentralRepoException("Central Repository module is not enabled", Bundle.PostgresEamDb_centralRepoDisabled_message()); // NON-NLS
196 }
197
198 if (connectionPool == null) {
199 setupConnectionPool();
200 }
201 try {
202 return connectionPool.getConnection();
203 } catch (SQLException ex) {
204 throw new CentralRepoException("Error getting connection from connection pool.", Bundle.PostgresEamDb_connectionFailed_message(), ex); // NON-NLS
205 }
206 }
207 }
208
209 @Override
210 protected String getConflictClause() {
211 return CONFLICT_CLAUSE;
212 }
213
214 @Override
215 protected Connection getEphemeralConnection() {
216 return this.dbSettings.getEphemeralConnection(false);
217 }
229 @Override
230 @Messages({"PostgresEamDb.multiUserLockError.message=Error acquiring database lock"})
231 public CoordinationService.Lock getExclusiveMultiUserDbLock() throws CentralRepoException {
232 try {
233 // First check if multi user mode is enabled - if not there's no point trying to get a lock
234 if (!UserPreferences.getIsMultiUserModeEnabled()) {
235 return null;
236 }
237
238 String databaseNodeName = dbSettings.getHost() + "_" + dbSettings.getDbName();
239 CoordinationService.Lock lock = CoordinationService.getInstance().tryGetExclusiveLock(CoordinationService.CategoryNode.CENTRAL_REPO, databaseNodeName, 5, TimeUnit.MINUTES);
240
241 if (lock != null) {
242 return lock;
243 }
244 throw new CentralRepoException("Error acquiring database lock", Bundle.PostgresEamDb_multiUserLockError_message());
245 } catch (InterruptedException ex) {
246 throw new CentralRepoException("Error acquiring database lock", Bundle.PostgresEamDb_multiUserLockError_message(), ex);
247 } catch (CoordinationService.CoordinationServiceException ex) {
248 // This likely just means the coordination service isn't running, which is ok
249 return null;
250 }
251 }
252
253 @Override
254 boolean doesColumnExist(Connection conn, String tableName, String columnName) throws SQLException {
255 final String objectIdColumnExistsTemplate = "SELECT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='%s' AND column_name='%s')"; //NON-NLS
256 ResultSet resultSet = null;
257 Statement statement = null;
258 boolean columnExists = false;
259 try {
260 statement = conn.createStatement();
261 resultSet = statement.executeQuery(String.format(objectIdColumnExistsTemplate, tableName, columnName));
262 if (resultSet.next()) {
263 columnExists = resultSet.getBoolean(1);
264 }
265 } finally {
266 CentralRepoDbUtil.closeResultSet(resultSet);
267 CentralRepoDbUtil.closeStatement(statement);
268 }
269 return columnExists;
270 }
271
272
273}

Copyright © 2012-2024 Sleuth Kit Labs. Generated on:
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.