Autopsy  4.9.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
PostgresEamDb.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  */
19 package org.sleuthkit.autopsy.centralrepository.datamodel;
20 
21 import java.sql.Connection;
22 import java.sql.ResultSet;
23 import java.sql.SQLException;
24 import java.sql.Statement;
25 import java.util.concurrent.TimeUnit;
26 import java.util.logging.Level;
27 import org.apache.commons.dbcp2.BasicDataSource;
31 
35 final class PostgresEamDb extends AbstractSqlEamDb {
36 
37  private final static Logger LOGGER = Logger.getLogger(PostgresEamDb.class.getName());
38 
39  private final static String CONFLICT_CLAUSE = "ON CONFLICT DO NOTHING";
40 
41  private static PostgresEamDb instance;
42 
43  private static final int CONN_POOL_SIZE = 10;
44  private BasicDataSource connectionPool = null;
45 
46  private final PostgresEamDbSettings dbSettings;
47 
56  public synchronized static PostgresEamDb getInstance() throws EamDbException {
57  if (instance == null) {
58  instance = new PostgresEamDb();
59  }
60 
61  return instance;
62  }
63 
70  private PostgresEamDb() throws EamDbException {
71  dbSettings = new PostgresEamDbSettings();
72  bulkArtifactsThreshold = dbSettings.getBulkThreshold();
73  }
74 
75  @Override
76  public void shutdownConnections() throws EamDbException {
77  try {
78  synchronized (this) {
79  if (connectionPool != null) {
80  connectionPool.close();
81  connectionPool = null; // force it to be re-created on next connect()
82  }
83  clearCaches();
84  }
85  } catch (SQLException ex) {
86  throw new EamDbException("Failed to close existing database connections.", ex); // NON-NLS
87  }
88  }
89 
90  @Override
91  public void updateSettings() {
92  synchronized (this) {
93  dbSettings.loadSettings();
94  bulkArtifactsThreshold = dbSettings.getBulkThreshold();
95  }
96  }
97 
98  @Override
99  public void saveSettings() {
100  synchronized (this) {
101  dbSettings.saveSettings();
102  }
103  }
104 
105  @Override
106  public void reset() throws EamDbException {
107  Connection conn = connect();
108 
109  try {
110  Statement dropContent = conn.createStatement();
111  dropContent.executeUpdate("TRUNCATE TABLE organizations RESTART IDENTITY CASCADE");
112  dropContent.executeUpdate("TRUNCATE TABLE cases RESTART IDENTITY CASCADE");
113  dropContent.executeUpdate("TRUNCATE TABLE data_sources RESTART IDENTITY CASCADE");
114  dropContent.executeUpdate("TRUNCATE TABLE reference_sets RESTART IDENTITY CASCADE");
115  dropContent.executeUpdate("TRUNCATE TABLE correlation_types RESTART IDENTITY CASCADE");
116  dropContent.executeUpdate("TRUNCATE TABLE db_info RESTART IDENTITY CASCADE");
117 
118  String instancesTemplate = "TRUNCATE TABLE %s_instances RESTART IDENTITY CASCADE";
119  String referencesTemplate = "TRUNCATE TABLE reference_%s RESTART IDENTITY CASCADE";
120  for (CorrelationAttributeInstance.Type type : defaultCorrelationTypes) {
121  dropContent.executeUpdate(String.format(instancesTemplate, type.getDbTableName()));
122  // FUTURE: support other reference types
123  if (type.getId() == CorrelationAttributeInstance.FILES_TYPE_ID) {
124  dropContent.executeUpdate(String.format(referencesTemplate, type.getDbTableName()));
125  }
126  }
127  } catch (SQLException ex) {
128  LOGGER.log(Level.WARNING, "Failed to reset database.", ex);
129  } finally {
130  EamDbUtil.closeConnection(conn);
131  }
132 
133  dbSettings.insertDefaultDatabaseContent();
134  }
135 
140  private void setupConnectionPool() throws EamDbException {
141  connectionPool = new BasicDataSource();
142  connectionPool.setUsername(dbSettings.getUserName());
143  connectionPool.setPassword(dbSettings.getPassword());
144  connectionPool.setDriverClassName(dbSettings.getDriver());
145 
146  StringBuilder connectionURL = new StringBuilder();
147  connectionURL.append(dbSettings.getJDBCBaseURI());
148  connectionURL.append(dbSettings.getHost());
149  connectionURL.append(":");
150  connectionURL.append(dbSettings.getPort());
151  connectionURL.append("/");
152  connectionURL.append(dbSettings.getDbName());
153 
154  connectionPool.setUrl(connectionURL.toString());
155  connectionPool.setUsername(dbSettings.getUserName());
156  connectionPool.setPassword(dbSettings.getPassword());
157 
158  // tweak pool configuration
159  connectionPool.setInitialSize(5); // start with 5 connections
160  connectionPool.setMaxIdle(CONN_POOL_SIZE); // max of 10 idle connections
161  connectionPool.setValidationQuery(dbSettings.getValidationQuery());
162  }
163 
171  @Override
172  protected Connection connect() throws EamDbException {
173  synchronized (this) {
174  if (!EamDb.isEnabled()) {
175  throw new EamDbException("Central Repository module is not enabled"); // NON-NLS
176  }
177 
178  if (connectionPool == null) {
179  setupConnectionPool();
180  }
181  }
182 
183  try {
184  return connectionPool.getConnection();
185  } catch (SQLException ex) {
186  throw new EamDbException("Error getting connection from connection pool.", ex); // NON-NLS
187  }
188  }
189 
190  @Override
191  protected String getConflictClause() {
192  return CONFLICT_CLAUSE;
193  }
194 
206  @Override
207  public CoordinationService.Lock getExclusiveMultiUserDbLock() throws EamDbException {
208  try {
209  // First check if multi user mode is enabled - if not there's no point trying to get a lock
210  if (!UserPreferences.getIsMultiUserModeEnabled()) {
211  return null;
212  }
213 
214  String databaseNodeName = dbSettings.getHost() + "_" + dbSettings.getDbName();
215  CoordinationService.Lock lock = CoordinationService.getInstance().tryGetExclusiveLock(CoordinationService.CategoryNode.CENTRAL_REPO, databaseNodeName, 5, TimeUnit.MINUTES);
216 
217  if (lock != null) {
218  return lock;
219  }
220  throw new EamDbException("Error acquiring database lock");
221  } catch (InterruptedException ex) {
222  throw new EamDbException("Error acquiring database lock");
223  } catch (CoordinationService.CoordinationServiceException ex) {
224  // This likely just means the coordination service isn't running, which is ok
225  return null;
226  }
227  }
228 
229  @Override
230  boolean doesColumnExist(Connection conn, String tableName, String columnName) throws SQLException {
231  final String objectIdColumnExistsTemplate = "SELECT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='%s' AND column_name='%s')"; //NON-NLS
232  ResultSet resultSet = null;
233  Statement statement = null;
234  boolean columnExists = false;
235  try {
236  statement = conn.createStatement();
237  resultSet = statement.executeQuery(String.format(objectIdColumnExistsTemplate, tableName, columnName));
238  if (resultSet.next()) {
239  columnExists = resultSet.getBoolean(1);
240  }
241  } finally {
242  EamDbUtil.closeResultSet(resultSet);
243  EamDbUtil.closeStatement(statement);
244  }
245  return columnExists;
246  }
247 
248 }
synchronized static Logger getLogger(String name)
Definition: Logger.java:124

Copyright © 2012-2018 Basis Technology. Generated on: Tue Dec 18 2018
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.