2 * ============LICENSE_START=======================================================
3 * feature-state-management
4 * ================================================================================
5 * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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 * ============LICENSE_END=========================================================
21 package org.onap.policy.drools.statemanagement;
23 import java.sql.Connection;
24 import java.sql.DriverManager;
25 import java.sql.PreparedStatement;
26 import java.sql.ResultSet;
27 import java.sql.SQLException;
28 import java.util.Properties;
29 import java.util.UUID;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
34 /** This class audits the database.
36 public class DbAudit extends DroolsPDPIntegrityMonitor.AuditBase {
37 // get an instance of logger
38 private static Logger logger = LoggerFactory.getLogger(DbAudit.class);
39 // single global instance of this audit object
40 private static final DbAudit instance = new DbAudit();
42 // This indicates if 'CREATE TABLE IF NOT EXISTS Audit ...' should be
43 // invoked -- doing this avoids the need to create the table in advance.
44 private static boolean createTableNeeded = true;
46 private static boolean isJunit = false;
48 /** Constructor - set the name to 'Database'. */
53 private static synchronized void setCreateTableNeeded(boolean isNeeded) {
54 DbAudit.createTableNeeded = isNeeded;
57 public static synchronized void setIsJunit(boolean isJUnit) {
58 DbAudit.isJunit = isJUnit;
61 public static boolean isJunit() {
62 return DbAudit.isJunit;
68 * @return the single 'DbAudit' instance. */
69 public static DroolsPDPIntegrityMonitor.AuditBase getInstance() {
76 * @param properties properties to be passed to the audit
79 public void invoke(Properties properties) {
80 logger.debug("Running 'DbAudit.invoke'");
81 boolean doCreate = createTableNeeded && !isJunit;
84 logger.info("DbAudit.invoke: exiting because isActive = false");
88 // fetch DB properties from properties file -- they are already known
89 // to exist, because they were verified by the 'IntegrityMonitor'
91 String url = properties.getProperty(StateManagementProperties.DB_URL);
92 String user = properties.getProperty(StateManagementProperties.DB_USER);
93 String password = properties.getProperty(StateManagementProperties.DB_PWD);
95 // operation phase currently running -- used to construct an error
99 // create connection to DB
100 phase = "creating connection";
101 logger.debug("DbAudit: Creating connection to {}", url);
102 try (Connection connection = DriverManager.getConnection(url, user, password)) {
104 // create audit table, if needed
106 phase = "create table";
107 createTable(connection);
110 // insert an entry into the table
111 phase = "insert entry";
112 String key = UUID.randomUUID().toString();
113 insertEntry(connection, key);
115 phase = "fetch entry";
116 findEntry(connection, key);
118 phase = "delete entry";
119 deleteEntry(connection, key);
120 } catch (Exception e) {
121 String message = "DbAudit: Exception during audit, phase = " + phase;
122 logger.error(message, e);
123 setResponse(message);
128 * Determines if the DbAudit is active, based on properties. Defaults to {@code true}, if not
129 * found in the properties.
131 * @return {@code true} if DbAudit is active, {@code false} otherwise
133 private boolean isActive() {
134 String dbAuditIsActive = StateManagementProperties.getProperty("db.audit.is.active");
135 logger.debug("DbAudit.invoke: dbAuditIsActive = {}", dbAuditIsActive);
137 if (dbAuditIsActive != null) {
139 return Boolean.parseBoolean(dbAuditIsActive.trim());
140 } catch (NumberFormatException e) {
142 "DbAudit.invoke: Ignoring invalid property: db.audit.is.active = {}", dbAuditIsActive);
152 * @param connection connection
153 * @throws SQLException exception
155 private void createTable(Connection connection) throws SQLException {
156 logger.info("DbAudit: Creating 'Audit' table, if needed");
157 try (PreparedStatement statement =
158 connection.prepareStatement(
159 "CREATE TABLE IF NOT EXISTS Audit (\n"
160 + " name varchar(64) DEFAULT NULL,\n"
161 + " UNIQUE KEY name (name)\n"
162 + ") DEFAULT CHARSET=latin1;")) {
164 DbAudit.setCreateTableNeeded(false);
171 * @param connection connection
173 * @throws SQLException exception
175 private void insertEntry(Connection connection, String key) throws SQLException {
176 try (PreparedStatement statement =
177 connection.prepareStatement("INSERT INTO Audit (name) VALUES (?)")) {
178 statement.setString(1, key);
179 statement.executeUpdate();
186 * @param connection connection
188 * @throws SQLException exception
190 private void findEntry(Connection connection, String key) throws SQLException {
191 try (PreparedStatement statement =
192 connection.prepareStatement("SELECT name FROM Audit WHERE name = ?")) {
193 statement.setString(1, key);
194 getEntry(statement, key);
199 * Executes the query to determine if the entry exists. Sets the response if it fails.
201 * @param statement statement
203 * @throws SQLException exception
205 private void getEntry(PreparedStatement statement, String key) throws SQLException {
206 try (ResultSet rs = statement.executeQuery()) {
209 if (logger.isDebugEnabled()) {
210 logger.debug("DbAudit: Found key {}", rs.getString(1));
213 logger.error("DbAudit: can't find newly-created entry with key {}", key);
214 setResponse("Can't find newly-created entry");
222 * @param connection connection
224 * @throws SQLException exception
226 private void deleteEntry(Connection connection, String key) throws SQLException {
227 try (PreparedStatement statement =
228 connection.prepareStatement("DELETE FROM Audit WHERE name = ?")) {
229 statement.setString(1, key);
230 statement.executeUpdate();