1 /*******************************************************************************
\r
2 * ============LICENSE_START==================================================
\r
4 * * ===========================================================================
\r
5 * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
\r
6 * * ===========================================================================
\r
7 * * Licensed under the Apache License, Version 2.0 (the "License");
\r
8 * * you may not use this file except in compliance with the License.
\r
9 * * You may obtain a copy of the License at
\r
11 * * http://www.apache.org/licenses/LICENSE-2.0
\r
13 * * Unless required by applicable law or agreed to in writing, software
\r
14 * * distributed under the License is distributed on an "AS IS" BASIS,
\r
15 * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
16 * * See the License for the specific language governing permissions and
\r
17 * * limitations under the License.
\r
18 * * ============LICENSE_END====================================================
\r
20 * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
\r
22 ******************************************************************************/
\r
25 package org.onap.dmaap.datarouter.provisioning.utils;
\r
27 import static java.lang.System.exit;
\r
28 import static java.lang.System.getProperty;
\r
30 import com.att.eelf.configuration.EELFLogger;
\r
31 import com.att.eelf.configuration.EELFManager;
\r
32 import java.io.File;
\r
33 import java.io.FileInputStream;
\r
34 import java.io.FileReader;
\r
35 import java.io.IOException;
\r
36 import java.io.LineNumberReader;
\r
37 import java.sql.Connection;
\r
38 import java.sql.DatabaseMetaData;
\r
39 import java.sql.DriverManager;
\r
40 import java.sql.ResultSet;
\r
41 import java.sql.SQLException;
\r
42 import java.sql.Statement;
\r
43 import java.util.HashSet;
\r
44 import java.util.LinkedList;
\r
45 import java.util.NoSuchElementException;
\r
46 import java.util.Properties;
\r
47 import java.util.Queue;
\r
48 import java.util.Set;
\r
51 * Load the DB JDBC driver, and manage a simple pool of connections to the DB.
\r
53 * @author Robert Eby
\r
58 private static EELFLogger intlogger = EELFManager.getInstance().getLogger("InternalLog");
\r
60 private static String dbUrl;
\r
61 private static String dbLogin;
\r
62 private static String dbPassword;
\r
63 private static Properties props;
\r
64 private static final Queue<Connection> queue = new LinkedList<>();
\r
66 private static String httpsPort;
\r
67 private static String httpPort;
\r
70 * Construct a DB object. If this is the very first creation of this object, it will load a copy of the properties
\r
71 * for the server, and attempt to load the JDBC driver for the database. If a fatal error occurs (e.g. either the
\r
72 * properties file or the DB driver is missing), the JVM will exit.
\r
75 if (props == null) {
\r
76 props = new Properties();
\r
78 props.load(new FileInputStream(getProperty(
\r
79 "org.onap.dmaap.datarouter.provserver.properties",
\r
80 "/opt/app/datartr/etc/provserver.properties")));
\r
81 String dbDriver = (String) props.get("org.onap.dmaap.datarouter.db.driver");
\r
82 dbUrl = (String) props.get("org.onap.dmaap.datarouter.db.url");
\r
83 dbLogin = (String) props.get("org.onap.dmaap.datarouter.db.login");
\r
84 dbPassword = (String) props.get("org.onap.dmaap.datarouter.db.password");
\r
85 httpsPort = (String) props.get("org.onap.dmaap.datarouter.provserver.https.port");
\r
86 httpPort = (String) props.get("org.onap.dmaap.datarouter.provserver.http.port");
\r
87 Class.forName(dbDriver);
\r
88 } catch (IOException e) {
\r
89 intlogger.error("PROV9003 Opening properties: " + e.getMessage(), e);
\r
91 } catch (ClassNotFoundException e) {
\r
92 intlogger.error("PROV9004 cannot find the DB driver: " + e);
\r
99 * Get the provisioning server properties (loaded from provserver.properties).
\r
101 * @return the Properties object
\r
103 public Properties getProperties() {
\r
108 * Get a JDBC connection to the DB from the pool. Creates a new one if none are available.
\r
110 * @return the Connection
\r
112 public Connection getConnection() throws SQLException {
\r
113 Connection connection = null;
\r
114 while (connection == null) {
\r
115 synchronized (queue) {
\r
117 connection = queue.remove();
\r
118 } catch (NoSuchElementException nseEx) {
\r
119 intlogger.error("PROV9006 No connection on queue: " + nseEx.getMessage(), nseEx);
\r
122 // Try up to 3 times to get a connection
\r
124 connection = DriverManager.getConnection(dbUrl, dbLogin, dbPassword);
\r
125 } catch (SQLException sqlEx) {
\r
130 } while (connection == null);
\r
133 if (connection != null && !connection.isValid(1)) {
\r
134 connection.close();
\r
142 * Returns a JDBC connection to the pool.
\r
144 * @param connection the Connection to return
\r
146 public void release(Connection connection) {
\r
147 if (connection != null) {
\r
148 synchronized (queue) {
\r
149 if (!queue.contains(connection)) {
\r
150 queue.add(connection);
\r
157 * Run all necessary retrofits required to bring the database up to the level required for this version of the
\r
158 * provisioning server. This should be run before the server itself is started.
\r
160 * @return true if all retrofits worked, false otherwise
\r
162 public boolean runRetroFits() {
\r
163 return retroFit1();
\r
167 public static String getHttpsPort() {
\r
171 public static String getHttpPort() {
\r
176 * Retrofit 1 - Make sure the expected tables are in DB and are initialized. Uses sql_init_01.sql to setup the DB.
\r
178 * @return true if the retrofit worked, false otherwise
\r
180 private boolean retroFit1() {
\r
181 final String[] expectedTables = {
\r
182 "FEEDS", "FEED_ENDPOINT_ADDRS", "FEED_ENDPOINT_IDS", "PARAMETERS",
\r
183 "SUBSCRIPTIONS", "LOG_RECORDS", "INGRESS_ROUTES", "EGRESS_ROUTES",
\r
184 "NETWORK_ROUTES", "NODESETS", "NODES", "GROUPS"
\r
186 Connection connection = null;
\r
188 connection = getConnection();
\r
189 Set<String> actualTables = getTableSet(connection);
\r
190 boolean initialize = false;
\r
191 for (String tableName : expectedTables) {
\r
192 initialize |= !actualTables.contains(tableName);
\r
195 intlogger.info("PROV9001: First time startup; The database is being initialized.");
\r
196 runInitScript(connection, 1);
\r
198 } catch (SQLException e) {
\r
199 intlogger.error("PROV9000: The database credentials are not working: " + e.getMessage(), e);
\r
202 if (connection != null) {
\r
203 release(connection);
\r
210 * Get a set of all table names in the DB.
\r
212 * @param connection a DB connection
\r
213 * @return the set of table names
\r
215 private Set<String> getTableSet(Connection connection) {
\r
216 Set<String> tables = new HashSet<>();
\r
218 DatabaseMetaData md = connection.getMetaData();
\r
219 ResultSet rs = md.getTables(null, null, "%", null);
\r
221 while (rs.next()) {
\r
222 tables.add(rs.getString("TABLE_NAME").toUpperCase());
\r
226 } catch (SQLException e) {
\r
227 intlogger.error("PROV9010: Failed to get TABLE data from DB: " + e.getMessage(), e);
\r
233 * Initialize the tables by running the initialization scripts located in the directory specified by the property
\r
234 * <i>org.onap.dmaap.datarouter.provserver.dbscripts</i>. Scripts have names of the form
\r
237 * @param connection a DB connection
\r
238 * @param scriptId the number of the sql_init_NN.sql script to run
\r
240 private void runInitScript(Connection connection, int scriptId) {
\r
241 String scriptDir = (String) props.get("org.onap.dmaap.datarouter.provserver.dbscripts");
\r
242 String scriptFile = String.format("%s/sql_init_%02d.sql", scriptDir, scriptId);
\r
243 if (!(new File(scriptFile)).exists()) {
\r
244 intlogger.error("PROV9005 Failed to load sql script from : " + scriptFile);
\r
247 try (LineNumberReader lineReader = new LineNumberReader(new FileReader(scriptFile));
\r
248 Statement statement = connection.createStatement()) {
\r
249 StringBuilder strBuilder = new StringBuilder();
\r
251 while ((line = lineReader.readLine()) != null) {
\r
252 if (!line.startsWith("--")) {
\r
253 line = line.trim();
\r
254 strBuilder.append(line);
\r
255 executeDdlStatement(statement, strBuilder, line);
\r
258 strBuilder.setLength(0);
\r
259 } catch (Exception e) {
\r
260 intlogger.error("PROV9002 Error when initializing table: " + e.getMessage(), e);
\r
265 private void executeDdlStatement(Statement statement, StringBuilder strBuilder, String line) throws SQLException {
\r
266 if (line.endsWith(";")) {
\r
267 // Execute one DDL statement
\r
268 String sql = strBuilder.toString();
\r
269 strBuilder.setLength(0);
\r
270 statement.execute(sql);
\r