Refactor Prov DB handling
[dmaap/datarouter.git] / datarouter-prov / src / main / java / org / onap / dmaap / datarouter / provisioning / utils / ProvDbUtils.java
1 /*
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2019 Nordix Foundation.
4  * ================================================================================
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * SPDX-License-Identifier: Apache-2.0
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.dmaap.datarouter.provisioning.utils;
22
23 import static java.lang.System.exit;
24
25 import com.att.eelf.configuration.EELFLogger;
26 import com.att.eelf.configuration.EELFManager;
27 import java.io.File;
28 import java.io.FileReader;
29 import java.io.LineNumberReader;
30 import java.sql.Connection;
31 import java.sql.DatabaseMetaData;
32 import java.sql.ResultSet;
33 import java.sql.SQLException;
34 import java.sql.Statement;
35 import java.util.HashSet;
36 import java.util.Properties;
37 import java.util.Set;
38 import javax.sql.DataSource;
39 import org.apache.commons.dbcp2.BasicDataSource;
40 import org.onap.dmaap.datarouter.provisioning.ProvRunner;
41
42 public class ProvDbUtils {
43
44     private static EELFLogger intLogger = EELFManager.getInstance().getLogger("InternalLog");
45     private static DataSource dataSource;
46     private static ProvDbUtils provDbUtils;
47
48     private ProvDbUtils() {
49     }
50
51     public static ProvDbUtils getInstance() {
52         if (provDbUtils == null) {
53             try {
54                 provDbUtils = new ProvDbUtils();
55                 dataSource = setupDataSource(ProvRunner.getProvProperties());
56             } catch (ClassNotFoundException e) {
57                 intLogger.error("PROV9010: Failed to load DB Driver Class: " + e.getMessage(), e);
58                 exit(1);
59             }
60         }
61         return provDbUtils;
62     }
63
64     private static DataSource setupDataSource(Properties props) throws ClassNotFoundException {
65         intLogger.info("PROV9009: Setting up DB dataSource");
66         Class.forName((String) props.get("org.onap.dmaap.datarouter.db.driver"));
67         BasicDataSource dataSource = new BasicDataSource();
68         dataSource.setUrl((String) props.get("org.onap.dmaap.datarouter.db.url"));
69         dataSource.setUsername((String) props.get("org.onap.dmaap.datarouter.db.login"));
70         dataSource.setPassword((String) props.get("org.onap.dmaap.datarouter.db.password"));
71         dataSource.setMinIdle(5);
72         dataSource.setMaxIdle(15);
73         dataSource.setMaxOpenPreparedStatements(100);
74         return dataSource;
75     }
76
77     public Connection getConnection() throws SQLException {
78         return dataSource.getConnection();
79     }
80
81     public boolean initProvDB() {
82         final String[] expectedTables = {
83             "FEEDS", "FEED_ENDPOINT_ADDRS", "FEED_ENDPOINT_IDS", "PARAMETERS",
84             "SUBSCRIPTIONS", "LOG_RECORDS", "INGRESS_ROUTES", "EGRESS_ROUTES",
85             "NETWORK_ROUTES", "NODESETS", "NODES", "GROUPS"
86         };
87         try (Connection connection = getConnection()) {
88             Set<String> actualTables = getTableSet(connection);
89             boolean initialize = false;
90             for (String tableName : expectedTables) {
91                 initialize |= !actualTables.contains(tableName);
92             }
93             if (initialize) {
94                 intLogger.info("PROV9001: First time startup; The database is being initialized.");
95                 runInitScript(connection, 1);
96             }
97         } catch (SQLException e) {
98             intLogger.error("PROV9000: The database credentials are not working: " + e.getMessage(), e);
99             return false;
100         }
101         return true;
102     }
103
104     /**
105      * Get a set of all table names in the DB.
106      *
107      * @param connection a DB connection
108      * @return the set of table names
109      */
110     private Set<String> getTableSet(Connection connection) {
111         Set<String> tables = new HashSet<>();
112         try {
113             DatabaseMetaData md = connection.getMetaData();
114             ResultSet rs = md.getTables(null, null, "%", null);
115             if (rs != null) {
116                 while (rs.next()) {
117                     tables.add(rs.getString("TABLE_NAME").toUpperCase());
118                 }
119                 rs.close();
120             }
121         } catch (SQLException e) {
122             intLogger.error("PROV9010: Failed to get TABLE data from DB: " + e.getMessage(), e);
123         }
124         return tables;
125     }
126
127     /**
128      * Initialize the tables by running the initialization scripts located in the directory specified by the property
129      * <i>org.onap.dmaap.datarouter.provserver.dbscripts</i>.  Scripts have names of the form
130      * sql_init_NN.sql
131      *
132      * @param connection a DB connection
133      * @param scriptId the number of the sql_init_NN.sql script to run
134      */
135     private void runInitScript(Connection connection, int scriptId) {
136         String scriptDir = ProvRunner.getProvProperties().getProperty("org.onap.dmaap.datarouter.provserver.dbscripts");
137         String scriptFile = String.format("%s/sql_init_%02d.sql", scriptDir, scriptId);
138         if (!(new File(scriptFile)).exists()) {
139             intLogger.error("PROV9005 Failed to load sql script from : " + scriptFile);
140             exit(1);
141         }
142         try (LineNumberReader lineReader = new LineNumberReader(new FileReader(scriptFile));
143             Statement statement = connection.createStatement()) {
144             StringBuilder strBuilder = new StringBuilder();
145             String line;
146             while ((line = lineReader.readLine()) != null) {
147                 if (!line.startsWith("--")) {
148                     line = line.trim();
149                     strBuilder.append(line);
150                     executeDdlStatement(statement, strBuilder, line);
151                 }
152             }
153             strBuilder.setLength(0);
154         } catch (Exception e) {
155             intLogger.error("PROV9002 Error when initializing table: " + e.getMessage(), e);
156             exit(1);
157         }
158     }
159
160
161     private void executeDdlStatement(Statement statement, StringBuilder strBuilder, String line) throws SQLException {
162         if (line.endsWith(";")) {
163             String sql = strBuilder.toString();
164             strBuilder.setLength(0);
165             statement.execute(sql);
166         }
167     }
168 }