-/*******************************************************************************\r
- * ============LICENSE_START==================================================\r
- * * org.onap.dmaap\r
- * * ===========================================================================\r
- * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.\r
- * * ===========================================================================\r
- * * Licensed under the Apache License, Version 2.0 (the "License");\r
- * * you may not use this file except in compliance with the License.\r
- * * You may obtain a copy of the License at\r
- * *\r
- * * http://www.apache.org/licenses/LICENSE-2.0\r
- * *\r
- * * Unless required by applicable law or agreed to in writing, software\r
- * * distributed under the License is distributed on an "AS IS" BASIS,\r
- * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * * See the License for the specific language governing permissions and\r
- * * limitations under the License.\r
- * * ============LICENSE_END====================================================\r
- * *\r
- * * ECOMP is a trademark and service mark of AT&T Intellectual Property.\r
- * *\r
- ******************************************************************************/\r
-\r
-package org.onap.dmaap.datarouter.provisioning.utils;\r
-\r
-import static java.lang.System.exit;\r
-import static java.lang.System.getProperty;\r
-\r
-import com.att.eelf.configuration.EELFLogger;\r
-import com.att.eelf.configuration.EELFManager;\r
-import java.io.File;\r
-import java.io.FileInputStream;\r
-import java.io.FileReader;\r
-import java.io.IOException;\r
-import java.io.LineNumberReader;\r
-import java.sql.Connection;\r
-import java.sql.DatabaseMetaData;\r
-import java.sql.DriverManager;\r
-import java.sql.ResultSet;\r
-import java.sql.SQLException;\r
-import java.sql.Statement;\r
-import java.util.HashSet;\r
-import java.util.LinkedList;\r
-import java.util.NoSuchElementException;\r
-import java.util.Properties;\r
-import java.util.Queue;\r
-import java.util.Set;\r
-\r
-/**\r
- * Load the DB JDBC driver, and manage a simple pool of connections to the DB.\r
- *\r
- * @author Robert Eby\r
- * @version $Id$\r
- */\r
-public class DB {\r
-\r
- private static EELFLogger intlogger = EELFManager.getInstance().getLogger("InternalLog");\r
-\r
- private static String dbUrl;\r
- private static String dbLogin;\r
- private static String dbPassword;\r
- private static Properties props;\r
- private static final Queue<Connection> queue = new LinkedList<>();\r
-\r
- private static String httpsPort;\r
- private static String httpPort;\r
-\r
- /**\r
- * Construct a DB object. If this is the very first creation of this object, it will load a copy of the properties\r
- * for the server, and attempt to load the JDBC driver for the database. If a fatal error occurs (e.g. either the\r
- * properties file or the DB driver is missing), the JVM will exit.\r
- */\r
- public DB() {\r
- if (props == null) {\r
- props = new Properties();\r
- try {\r
- props.load(new FileInputStream(getProperty(\r
- "org.onap.dmaap.datarouter.provserver.properties",\r
- "/opt/app/datartr/etc/provserver.properties")));\r
- dbUrl = (String) props.get("org.onap.dmaap.datarouter.db.url");\r
- dbLogin = (String) props.get("org.onap.dmaap.datarouter.db.login");\r
- dbPassword = (String) props.get("org.onap.dmaap.datarouter.db.password");\r
- httpsPort = (String) props.get("org.onap.dmaap.datarouter.provserver.https.port");\r
- httpPort = (String) props.get("org.onap.dmaap.datarouter.provserver.http.port");\r
- String dbDriver = (String) props.get("org.onap.dmaap.datarouter.db.driver");\r
- Class.forName(dbDriver);\r
- } catch (IOException e) {\r
- intlogger.error("PROV9003 Opening properties: " + e.getMessage(), e);\r
- exit(1);\r
- } catch (ClassNotFoundException e) {\r
- intlogger.error("PROV9004 cannot find the DB driver: " + e);\r
- exit(1);\r
- }\r
- }\r
- }\r
-\r
- /**\r
- * Get the provisioning server properties (loaded from provserver.properties).\r
- *\r
- * @return the Properties object\r
- */\r
- public Properties getProperties() {\r
- return props;\r
- }\r
-\r
- /**\r
- * Get a JDBC connection to the DB from the pool. Creates a new one if none are available.\r
- *\r
- * @return the Connection\r
- */\r
- public Connection getConnection() throws SQLException {\r
- Connection connection = null;\r
- while (connection == null) {\r
- synchronized (queue) {\r
- try {\r
- connection = queue.remove();\r
- } catch (NoSuchElementException ignore) {\r
- int num = 0;\r
- do {\r
- // Try up to 3 times to get a connection\r
- try {\r
- connection = DriverManager.getConnection(dbUrl, dbLogin, dbPassword);\r
- } catch (SQLException sqlEx) {\r
- if (++num >= 3) {\r
- throw sqlEx;\r
- }\r
- }\r
- }\r
- while (connection == null);\r
- }\r
- }\r
- if (connection != null && !connection.isValid(1)) {\r
- connection.close();\r
- connection = null;\r
- }\r
- }\r
- return connection;\r
- }\r
-\r
- /**\r
- * Returns a JDBC connection to the pool.\r
- *\r
- * @param connection the Connection to return\r
- */\r
- public void release(Connection connection) {\r
- if (connection != null) {\r
- synchronized (queue) {\r
- if (!queue.contains(connection)) {\r
- queue.add(connection);\r
- }\r
- }\r
- }\r
- }\r
-\r
- /**\r
- * Run all necessary retrofits required to bring the database up to the level required for this version of the\r
- * provisioning server. This should be run before the server itself is started.\r
- *\r
- * @return true if all retrofits worked, false otherwise\r
- */\r
- public boolean runRetroFits() {\r
- return retroFit1();\r
- }\r
-\r
-\r
- public static String getHttpsPort() {\r
- return httpsPort;\r
- }\r
-\r
- public static String getHttpPort() {\r
- return httpPort;\r
- }\r
-\r
- /**\r
- * Retrofit 1 - Make sure the expected tables are in DB and are initialized. Uses sql_init_01.sql to setup the DB.\r
- *\r
- * @return true if the retrofit worked, false otherwise\r
- */\r
- private boolean retroFit1() {\r
- final String[] expectedTables = {\r
- "FEEDS", "FEED_ENDPOINT_ADDRS", "FEED_ENDPOINT_IDS", "PARAMETERS",\r
- "SUBSCRIPTIONS", "LOG_RECORDS", "INGRESS_ROUTES", "EGRESS_ROUTES",\r
- "NETWORK_ROUTES", "NODESETS", "NODES", "GROUPS"\r
- };\r
- Connection connection = null;\r
- try {\r
- connection = getConnection();\r
- Set<String> actualTables = getTableSet(connection);\r
- boolean initialize = false;\r
- for (String tableName : expectedTables) {\r
- initialize |= !actualTables.contains(tableName);\r
- }\r
- if (initialize) {\r
- intlogger.info("PROV9001: First time startup; The database is being initialized.");\r
- runInitScript(connection, 1);\r
- }\r
- } catch (SQLException e) {\r
- intlogger.error("PROV9000: The database credentials are not working: " + e.getMessage(), e);\r
- return false;\r
- } finally {\r
- if (connection != null) {\r
- release(connection);\r
- }\r
- }\r
- return true;\r
- }\r
-\r
- /**\r
- * Get a set of all table names in the DB.\r
- *\r
- * @param connection a DB connection\r
- * @return the set of table names\r
- */\r
- private Set<String> getTableSet(Connection connection) {\r
- Set<String> tables = new HashSet<>();\r
- try {\r
- DatabaseMetaData md = connection.getMetaData();\r
- ResultSet rs = md.getTables(null, null, "%", null);\r
- if (rs != null) {\r
- while (rs.next()) {\r
- tables.add(rs.getString("TABLE_NAME").toUpperCase());\r
- }\r
- rs.close();\r
- }\r
- } catch (SQLException e) {\r
- intlogger.error("PROV9010: Failed to get TABLE data from DB: " + e.getMessage(), e);\r
- }\r
- return tables;\r
- }\r
-\r
- /**\r
- * Initialize the tables by running the initialization scripts located in the directory specified by the property\r
- * <i>org.onap.dmaap.datarouter.provserver.dbscripts</i>. Scripts have names of the form\r
- * sql_init_NN.sql\r
- *\r
- * @param connection a DB connection\r
- * @param scriptId the number of the sql_init_NN.sql script to run\r
- */\r
- private void runInitScript(Connection connection, int scriptId) {\r
- String scriptDir = (String) props.get("org.onap.dmaap.datarouter.provserver.dbscripts");\r
- String scriptFile = String.format("%s/sql_init_%02d.sql", scriptDir, scriptId);\r
- if (!(new File(scriptFile)).exists()) {\r
- intlogger.error("PROV9005 Failed to load sql script from : " + scriptFile);\r
- exit(1);\r
- }\r
- try (LineNumberReader lineReader = new LineNumberReader(new FileReader(scriptFile));\r
- Statement statement = connection.createStatement()) {\r
- StringBuilder strBuilder = new StringBuilder();\r
- String line;\r
- while ((line = lineReader.readLine()) != null) {\r
- if (!line.startsWith("--")) {\r
- line = line.trim();\r
- strBuilder.append(line);\r
- executeDdlStatement(statement, strBuilder, line);\r
- }\r
- }\r
- strBuilder.setLength(0);\r
- } catch (Exception e) {\r
- intlogger.error("PROV9002 Error when initializing table: " + e.getMessage(), e);\r
- exit(1);\r
- }\r
- }\r
-\r
- private void executeDdlStatement(Statement statement, StringBuilder strBuilder, String line) throws SQLException {\r
- if (line.endsWith(";")) {\r
- // Execute one DDL statement\r
- String sql = strBuilder.toString();\r
- strBuilder.setLength(0);\r
- statement.execute(sql);\r
- }\r
- }\r
-}\r