Autopsy  4.13.0
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;
28 import org.openide.util.NbBundle.Messages;
32 
36 final class PostgresEamDb extends AbstractSqlEamDb {
37 
38  private final static Logger LOGGER = Logger.getLogger(PostgresEamDb.class.getName());
39 
40  private final static String CONFLICT_CLAUSE = "ON CONFLICT DO NOTHING";
41 
42  private static PostgresEamDb instance;
43 
44  private static final int CONN_POOL_SIZE = 10;
45  private BasicDataSource connectionPool = null;
46 
47  private final PostgresEamDbSettings dbSettings;
48 
57  public synchronized static PostgresEamDb getInstance() throws EamDbException {
58  if (instance == null) {
59  instance = new PostgresEamDb();
60  }
61 
62  return instance;
63  }
64 
71  private PostgresEamDb() throws EamDbException {
72  dbSettings = new PostgresEamDbSettings();
73  bulkArtifactsThreshold = dbSettings.getBulkThreshold();
74  }
75 
76  @Override
77  public void shutdownConnections() throws EamDbException {
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 EamDbException("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 EamDbException {
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  EamDbUtil.closeConnection(conn);
132  }
133 
134  dbSettings.insertDefaultDatabaseContent();
135  }
136 
141  private void setupConnectionPool() throws EamDbException {
142  connectionPool = new BasicDataSource();
143  connectionPool.setUsername(dbSettings.getUserName());
144  connectionPool.setPassword(dbSettings.getPassword());
145  connectionPool.setDriverClassName(dbSettings.getDriver());
146 
147  StringBuilder connectionURL = new StringBuilder();
148  connectionURL.append(dbSettings.getJDBCBaseURI());
149  connectionURL.append(dbSettings.getHost());
150  connectionURL.append(":");
151  connectionURL.append(dbSettings.getPort());
152  connectionURL.append("/");
153  connectionURL.append(dbSettings.getDbName());
154 
155  connectionPool.setUrl(connectionURL.toString());
156  connectionPool.setUsername(dbSettings.getUserName());
157  connectionPool.setPassword(dbSettings.getPassword());
158 
159  // tweak pool configuration
160  connectionPool.setInitialSize(5); // start with 5 connections
161  connectionPool.setMaxIdle(CONN_POOL_SIZE); // max of 10 idle connections
162  connectionPool.setValidationQuery(dbSettings.getValidationQuery());
163  }
164 
174  @Override
175  protected Connection connect(boolean foreignKeys) throws EamDbException {
176  //foreignKeys boolean is ignored for postgres
177  return connect();
178  }
179 
187  @Messages({"PostgresEamDb.centralRepoDisabled.message=Central Repository module is not enabled.",
188  "PostgresEamDb.connectionFailed.message=Error getting connection to database."})
189  @Override
190  protected Connection connect() throws EamDbException {
191  synchronized (this) {
192  if (!EamDb.isEnabled()) {
193  throw new EamDbException("Central Repository module is not enabled", Bundle.PostgresEamDb_centralRepoDisabled_message()); // NON-NLS
194  }
195 
196  if (connectionPool == null) {
197  setupConnectionPool();
198  }
199  }
200  try {
201  return connectionPool.getConnection();
202  } catch (SQLException ex) {
203  throw new EamDbException("Error getting connection from connection pool.", Bundle.PostgresEamDb_connectionFailed_message(), ex); // NON-NLS
204  }
205  }
206 
207  @Override
208  protected String getConflictClause() {
209  return CONFLICT_CLAUSE;
210  }
211 
223  @Override
224  @Messages({"PostgresEamDb.multiUserLockError.message=Error acquiring database lock"})
225  public CoordinationService.Lock getExclusiveMultiUserDbLock() throws EamDbException {
226  try {
227  // First check if multi user mode is enabled - if not there's no point trying to get a lock
228  if (!UserPreferences.getIsMultiUserModeEnabled()) {
229  return null;
230  }
231 
232  String databaseNodeName = dbSettings.getHost() + "_" + dbSettings.getDbName();
233  CoordinationService.Lock lock = CoordinationService.getInstance().tryGetExclusiveLock(CoordinationService.CategoryNode.CENTRAL_REPO, databaseNodeName, 5, TimeUnit.MINUTES);
234 
235  if (lock != null) {
236  return lock;
237  }
238  throw new EamDbException("Error acquiring database lock", Bundle.PostgresEamDb_multiUserLockError_message());
239  } catch (InterruptedException ex) {
240  throw new EamDbException("Error acquiring database lock", Bundle.PostgresEamDb_multiUserLockError_message(), ex);
241  } catch (CoordinationService.CoordinationServiceException ex) {
242  // This likely just means the coordination service isn't running, which is ok
243  return null;
244  }
245  }
246 
247  @Override
248  boolean doesColumnExist(Connection conn, String tableName, String columnName) throws SQLException {
249  final String objectIdColumnExistsTemplate = "SELECT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='%s' AND column_name='%s')"; //NON-NLS
250  ResultSet resultSet = null;
251  Statement statement = null;
252  boolean columnExists = false;
253  try {
254  statement = conn.createStatement();
255  resultSet = statement.executeQuery(String.format(objectIdColumnExistsTemplate, tableName, columnName));
256  if (resultSet.next()) {
257  columnExists = resultSet.getBoolean(1);
258  }
259  } finally {
260  EamDbUtil.closeResultSet(resultSet);
261  EamDbUtil.closeStatement(statement);
262  }
263  return columnExists;
264  }
265 
266 }
synchronized static Logger getLogger(String name)
Definition: Logger.java:124

Copyright © 2012-2019 Basis Technology. Generated on: Tue Jan 7 2020
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.