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 java.io.File;
\r
28 import java.io.FileReader;
\r
29 import java.io.IOException;
\r
30 import java.io.InputStream;
\r
31 import java.io.LineNumberReader;
\r
32 import java.lang.reflect.Constructor;
\r
33 import java.lang.reflect.InvocationTargetException;
\r
34 import java.sql.Connection;
\r
35 import java.sql.DatabaseMetaData;
\r
36 import java.sql.DriverManager;
\r
37 import java.sql.PreparedStatement;
\r
38 import java.sql.ResultSet;
\r
39 import java.sql.SQLException;
\r
40 import java.sql.Statement;
\r
41 import java.util.HashSet;
\r
42 import java.util.LinkedList;
\r
43 import java.util.NoSuchElementException;
\r
44 import java.util.Properties;
\r
45 import java.util.Queue;
\r
46 import java.util.Set;
\r
48 import org.apache.log4j.Logger;
\r
49 import org.onap.dmaap.datarouter.provisioning.beans.DeliveryRecord;
\r
50 import org.onap.dmaap.datarouter.provisioning.beans.ExpiryRecord;
\r
51 import org.onap.dmaap.datarouter.provisioning.beans.Loadable;
\r
52 import org.onap.dmaap.datarouter.provisioning.beans.PublishRecord;
\r
55 * Load the DB JDBC driver, and manage a simple pool of connections to the DB.
\r
57 * @author Robert Eby
\r
61 /** The name of the properties file (in CLASSPATH) */
\r
62 public static final String CONFIG_FILE = "provserver.properties";
\r
64 private static String DB_DRIVER = "com.mysql.jdbc.Driver";
\r
65 private static String DB_URL = "jdbc:mysql://127.0.0.1:3306/datarouter";
\r
66 private static String DB_LOGIN = "datarouter";
\r
67 private static String DB_PASSWORD = "datarouter";
\r
68 private static Properties props;
\r
69 private static Logger intlogger = Logger.getLogger("org.onap.dmaap.datarouter.provisioning.internal");
\r
70 private static Queue<Connection> queue = new LinkedList<Connection>();
\r
72 public static String HTTPS_PORT;
\r
73 public static String HTTP_PORT;
\r
76 * Construct a DB object. If this is the very first creation of this object, it will load a copy
\r
77 * of the properties for the server, and attempt to load the JDBC driver for the database. If a fatal
\r
78 * error occurs (e.g. either the properties file or the DB driver is missing), the JVM will exit.
\r
81 if (props == null) {
\r
82 props = new Properties();
\r
83 InputStream inStream = getClass().getClassLoader().getResourceAsStream(CONFIG_FILE);
\r
85 props.load(inStream);
\r
86 DB_DRIVER = (String) props.get("org.onap.dmaap.datarouter.db.driver");
\r
87 DB_URL = (String) props.get("org.onap.dmaap.datarouter.db.url");
\r
88 DB_LOGIN = (String) props.get("org.onap.dmaap.datarouter.db.login");
\r
89 DB_PASSWORD = (String) props.get("org.onap.dmaap.datarouter.db.password");
\r
90 HTTPS_PORT = (String) props.get("org.onap.dmaap.datarouter.provserver.https.port");
\r
91 HTTP_PORT = (String) props.get("org.onap.dmaap.datarouter.provserver.http.port");
\r
92 Class.forName(DB_DRIVER);
\r
93 } catch (IOException e) {
\r
94 intlogger.fatal("PROV9003 Opening properties: "+e.getMessage());
\r
95 e.printStackTrace();
\r
97 } catch (ClassNotFoundException e) {
\r
98 intlogger.fatal("PROV9004 cannot find the DB driver: "+e);
\r
99 e.printStackTrace();
\r
104 } catch (IOException e) {
\r
110 * Get the provisioning server properties (loaded from provserver.properties).
\r
111 * @return the Properties object
\r
113 public Properties getProperties() {
\r
117 * Get a JDBC connection to the DB from the pool. Creates a new one if none are available.
\r
118 * @return the Connection
\r
119 * @throws SQLException
\r
121 @SuppressWarnings("resource")
\r
122 public Connection getConnection() throws SQLException {
\r
123 Connection c = null;
\r
124 while (c == null) {
\r
125 synchronized (queue) {
\r
127 c = queue.remove();
\r
128 } catch (NoSuchElementException e) {
\r
131 // Try up to 3 times to get a connection
\r
133 c = DriverManager.getConnection(DB_URL, DB_LOGIN, DB_PASSWORD);
\r
134 } catch (SQLException e1) {
\r
138 } while (c == null);
\r
141 if (c != null && !c.isValid(1)) {
\r
149 * Returns a JDBC connection to the pool.
\r
150 * @param c the Connection to return
\r
151 * @throws SQLException
\r
153 public void release(Connection c) {
\r
155 synchronized (queue) {
\r
156 if (!queue.contains(c))
\r
163 * Run all necessary retrofits required to bring the database up to the level required for this version
\r
164 * of the provisioning server. This should be run before the server itself is started.
\r
165 * @return true if all retrofits worked, false otherwise
\r
167 public boolean runRetroFits() {
\r
176 && retroFit9() //New retroFit call to add CREATED_DATE column Rally:US674199 - 1610
\r
177 && retroFit10() //New retroFit call to add BUSINESS_DESCRIPTION column Rally:US708102 - 1610
\r
178 && retroFit11() //New retroFit call for groups feature Rally:US708115 - 1610
\r
182 * Retrofit 1 - Make sure the expected tables are in MySQL and are initialized.
\r
183 * Uses mysql_init_0000 and mysql_init_0001 to setup the DB.
\r
184 * @return true if the retrofit worked, false otherwise
\r
186 private boolean retroFit1() {
\r
187 final String[] expected_tables = {
\r
188 "FEEDS", "FEED_ENDPOINT_ADDRS", "FEED_ENDPOINT_IDS", "PARAMETERS", "SUBSCRIPTIONS"
\r
190 Connection c = null;
\r
192 c = getConnection();
\r
193 Set<String> tables = getTableSet(c);
\r
194 boolean initialize = false;
\r
195 for (String s : expected_tables) {
\r
196 initialize |= !tables.contains(s);
\r
199 intlogger.info("PROV9001: First time startup; The database is being initialized.");
\r
200 runInitScript(c, 0); // script 0 creates the provisioning tables
\r
201 runInitScript(c, 1); // script 1 initializes PARAMETERS
\r
203 } catch (SQLException e) {
\r
204 intlogger.fatal("PROV9000: The database credentials are not working: "+e.getMessage());
\r
213 * Retrofit 2 - if the LOG_RECORDS table is missing, add it.
\r
214 * Uses mysql_init_0002 to create this table.
\r
215 * @return true if the retrofit worked, false otherwise
\r
217 private boolean retroFit2() {
\r
218 Connection c = null;
\r
220 // If LOG_RECORDS table is missing, add it
\r
221 c = getConnection();
\r
222 Set<String> tables = getTableSet(c);
\r
223 if (!tables.contains("LOG_RECORDS")) {
\r
224 intlogger.info("PROV9002: Creating LOG_RECORDS table.");
\r
225 runInitScript(c, 2); // script 2 creates the LOG_RECORDS table
\r
227 } catch (SQLException e) {
\r
228 intlogger.fatal("PROV9000: The database credentials are not working: "+e.getMessage());
\r
237 * Retrofit 3 - if the FEEDS_UNIQUEID table (from release 1.0.*) exists, drop it.
\r
238 * If SUBSCRIPTIONS.SUBID still has the auto_increment attribute, remove it.
\r
239 * @return true if the retrofit worked, false otherwise
\r
241 @SuppressWarnings("resource")
\r
242 private boolean retroFit3() {
\r
243 Connection c = null;
\r
245 // if SUBSCRIPTIONS.SUBID still has auto_increment, remove it
\r
246 boolean doremove = false;
\r
247 c = getConnection();
\r
248 DatabaseMetaData md = c.getMetaData();
\r
249 ResultSet rs = md.getColumns("datarouter", "", "SUBSCRIPTIONS", "SUBID");
\r
251 while (rs.next()) {
\r
252 doremove = rs.getString("IS_AUTOINCREMENT").equals("YES");
\r
258 intlogger.info("PROV9002: Modifying SUBSCRIPTIONS SUBID column to remove auto increment.");
\r
259 Statement s = c.createStatement();
\r
260 s.execute("ALTER TABLE SUBSCRIPTIONS MODIFY COLUMN SUBID INT UNSIGNED NOT NULL");
\r
264 // Remove the FEEDS_UNIQUEID table, if it exists
\r
265 Set<String> tables = getTableSet(c);
\r
266 if (tables.contains("FEEDS_UNIQUEID")) {
\r
267 intlogger.info("PROV9002: Dropping FEEDS_UNIQUEID table.");
\r
268 Statement s = c.createStatement();
\r
269 s.execute("DROP TABLE FEEDS_UNIQUEID");
\r
272 } catch (SQLException e) {
\r
273 intlogger.fatal("PROV9000: The database credentials are not working: "+e.getMessage());
\r
281 private long nextid = 0; // used for initial creation of LOG_RECORDS table.
\r
283 * Retrofit 4 - if old log tables exist (from release 1.0.*), copy them to LOG_RECORDS, then drop them.
\r
284 * @return true if the retrofit worked, false otherwise
\r
286 @SuppressWarnings("resource")
\r
287 private boolean retroFit4() {
\r
288 Connection c = null;
\r
290 c = getConnection();
\r
291 Set<String> tables = getTableSet(c);
\r
292 if (tables.contains("PUBLISH_RECORDS")) {
\r
293 intlogger.info("PROV9002: Copying PUBLISH_RECORDS to LOG_RECORDS table.");
\r
294 copyLogTable("PUBLISH_RECORDS", PublishRecord.class);
\r
295 intlogger.info("PROV9002: Dropping PUBLISH_RECORDS table.");
\r
296 Statement s = c.createStatement();
\r
297 s.execute("DROP TABLE PUBLISH_RECORDS");
\r
300 if (tables.contains("DELIVERY_RECORDS")) {
\r
301 intlogger.info("PROV9002: Copying DELIVERY_RECORDS to LOG_RECORDS table.");
\r
302 copyLogTable("DELIVERY_RECORDS", DeliveryRecord.class);
\r
303 intlogger.info("PROV9002: Dropping DELIVERY_RECORDS table.");
\r
304 Statement s = c.createStatement();
\r
305 s.execute("DROP TABLE DELIVERY_RECORDS");
\r
308 if (tables.contains("EXPIRY_RECORDS")) {
\r
309 intlogger.info("PROV9002: Copying EXPIRY_RECORDS to LOG_RECORDS table.");
\r
310 copyLogTable("EXPIRY_RECORDS", ExpiryRecord.class);
\r
311 intlogger.info("PROV9002: Dropping EXPIRY_RECORDS table.");
\r
312 Statement s = c.createStatement();
\r
313 s.execute("DROP TABLE EXPIRY_RECORDS");
\r
316 } catch (SQLException e) {
\r
317 intlogger.fatal("PROV9000: The database credentials are not working: "+e.getMessage());
\r
326 * Retrofit 5 - Create the new routing tables required for Release 2.
\r
327 * Adds a new "SUSPENDED" column to FEEDS and SUBSCRIPTIONS.
\r
328 * Modifies the LOG_RECORDS table to handle new R2 records.
\r
329 * @return true if the retrofit worked, false otherwise
\r
331 @SuppressWarnings("resource")
\r
332 private boolean retroFit5() {
\r
333 final String[] expected_tables = {
\r
334 "INGRESS_ROUTES", "EGRESS_ROUTES", "NETWORK_ROUTES", "NODESETS", "NODES"
\r
336 Connection c = null;
\r
338 // If expected tables are not present, then add new routing tables
\r
339 c = getConnection();
\r
340 Set<String> tables = getTableSet(c);
\r
341 boolean initialize = false;
\r
342 for (String s : expected_tables) {
\r
343 initialize |= !tables.contains(s);
\r
346 intlogger.info("PROV9002: Adding routing tables for Release 2.0.");
\r
347 runInitScript(c, 3); // script 3 creates the routing tables
\r
350 // Add SUSPENDED column to FEEDS/SUBSCRIPTIONS
\r
351 DatabaseMetaData md = c.getMetaData();
\r
352 for (String tbl : new String[] {"FEEDS", "SUBSCRIPTIONS" }) {
\r
353 boolean add_col = true;
\r
354 ResultSet rs = md.getColumns("datarouter", "", tbl, "SUSPENDED");
\r
356 add_col = !rs.next();
\r
361 intlogger.info("PROV9002: Adding SUSPENDED column to "+tbl+" table.");
\r
362 Statement s = c.createStatement();
\r
363 s.execute("ALTER TABLE "+tbl+" ADD COLUMN SUSPENDED BOOLEAN DEFAULT FALSE");
\r
368 // Modify LOG_RECORDS for R2
\r
369 intlogger.info("PROV9002: Modifying LOG_RECORDS table.");
\r
370 Statement s = c.createStatement();
\r
371 s.execute("ALTER TABLE LOG_RECORDS MODIFY COLUMN TYPE ENUM('pub', 'del', 'exp', 'pbf', 'dlx') NOT NULL");
\r
373 s = c.createStatement();
\r
374 s.execute("ALTER TABLE LOG_RECORDS MODIFY COLUMN REASON ENUM('notRetryable', 'retriesExhausted', 'diskFull', 'other')");
\r
376 boolean add_col = true;
\r
377 ResultSet rs = md.getColumns("datarouter", "", "LOG_RECORDS", "CONTENT_LENGTH_2");
\r
379 add_col = !rs.next();
\r
384 intlogger.info("PROV9002: Fixing two columns in LOG_RECORDS table (this may take some time).");
\r
385 s = c.createStatement();
\r
386 s.execute("ALTER TABLE LOG_RECORDS MODIFY COLUMN CONTENT_LENGTH BIGINT NOT NULL, ADD COLUMN CONTENT_LENGTH_2 BIGINT AFTER RECORD_ID");
\r
389 } catch (SQLException e) {
\r
390 intlogger.fatal("PROV9000: The database credentials are not working: "+e.getMessage());
\r
399 * Retrofit 6 - Adjust LOG_RECORDS.USER to be 50 chars (MR #74).
\r
400 * @return true if the retrofit worked, false otherwise
\r
402 @SuppressWarnings("resource")
\r
403 private boolean retroFit6() {
\r
404 Connection c = null;
\r
406 c = getConnection();
\r
407 // Modify LOG_RECORDS for R2
\r
408 intlogger.info("PROV9002: Modifying LOG_RECORDS.USER length.");
\r
409 Statement s = c.createStatement();
\r
410 s.execute("ALTER TABLE LOG_RECORDS MODIFY COLUMN USER VARCHAR(50)");
\r
412 } catch (SQLException e) {
\r
413 intlogger.fatal("PROV9000: The database credentials are not working: "+e.getMessage());
\r
422 * Retrofit 7 - Adjust LOG_RECORDS.FEED_FILEID and LOG_RECORDS.DELIVERY_FILEID to be 256 chars.
\r
423 * @return true if the retrofit worked, false otherwise
\r
425 @SuppressWarnings("resource")
\r
426 private boolean retroFit7() {
\r
427 Connection c = null;
\r
429 c = getConnection();
\r
430 // Modify LOG_RECORDS for long (>128) FILEIDs
\r
431 intlogger.info("PROV9002: Modifying LOG_RECORDS.USER length.");
\r
432 Statement s = c.createStatement();
\r
433 s.execute("ALTER TABLE LOG_RECORDS MODIFY COLUMN FEED_FILEID VARCHAR(256), MODIFY COLUMN DELIVERY_FILEID VARCHAR(256)");
\r
435 } catch (SQLException e) {
\r
436 intlogger.fatal("PROV9000: The database credentials are not working: "+e.getMessage());
\r
445 * Retrofit 8 - Adjust FEEDS.NAME to be 255 chars (MR #74).
\r
446 * @return true if the retrofit worked, false otherwise
\r
448 @SuppressWarnings("resource")
\r
449 private boolean retroFit8() {
\r
450 Connection c = null;
\r
452 c = getConnection();
\r
453 intlogger.info("PROV9002: Modifying FEEDS.NAME length.");
\r
454 Statement s = c.createStatement();
\r
455 s.execute("ALTER TABLE FEEDS MODIFY COLUMN NAME VARCHAR(255)");
\r
457 } catch (SQLException e) {
\r
458 intlogger.fatal("PROV9000: The database credentials are not working: "+e.getMessage());
\r
468 * Retrofit 9 - Add column FEEDS.CREATED_DATE and SUBSCRIPTIONS.CREATED_DATE, 1610 release user story US674199.
\r
469 * @return true if the retrofit worked, false otherwise
\r
472 @SuppressWarnings("resource")
\r
473 private boolean retroFit9() {
\r
474 Connection c = null;
\r
476 c = getConnection();
\r
477 // Add CREATED_DATE column to FEEDS/SUBSCRIPTIONS tables
\r
478 DatabaseMetaData md = c.getMetaData();
\r
479 for (String tbl : new String[] {"FEEDS", "SUBSCRIPTIONS" }) {
\r
480 boolean add_col = true;
\r
481 ResultSet rs = md.getColumns("datarouter", "", tbl, "CREATED_DATE");
\r
483 add_col = !rs.next();
\r
488 intlogger.info("PROV9002: Adding CREATED_DATE column to "+tbl+" table.");
\r
489 Statement s = c.createStatement();
\r
490 s.execute("ALTER TABLE "+tbl+" ADD COLUMN CREATED_DATE timestamp DEFAULT CURRENT_TIMESTAMP");
\r
494 } catch (SQLException e) {
\r
495 intlogger.fatal("PROV9000: The database credentials are not working: "+e.getMessage());
\r
505 * Retrofit 10 -Adding business BUSINESS_DESCRIPTION to FEEDS table (Rally
\r
508 * @return true if the retrofit worked, false otherwise
\r
511 @SuppressWarnings("resource")
\r
512 private boolean retroFit10() {
\r
513 Connection c = null;
\r
514 boolean addColumn = true;
\r
518 c = getConnection();
\r
519 // Add BUSINESS_DESCRIPTION column to FEEDS table
\r
520 DatabaseMetaData md = c.getMetaData();
\r
521 boolean add_col = true;
\r
522 ResultSet rs = md.getColumns("datarouter", "", "FEEDS", "BUSINESS_DESCRIPTION");
\r
524 add_col = !rs.next();
\r
530 .info("PROV9002: Adding BUSINESS_DESCRIPTION column to FEEDS table.");
\r
531 Statement s = c.createStatement();
\r
532 s.execute("ALTER TABLE FEEDS ADD COLUMN BUSINESS_DESCRIPTION varchar(1000) DEFAULT NULL AFTER DESCRIPTION, MODIFY COLUMN DESCRIPTION VARCHAR(1000)");
\r
536 catch (SQLException e) {
\r
538 .fatal("PROV9000: The database credentials are not working: "
\r
549 /*New retroFit method is added for groups feature Rally:US708115 - 1610
\r
552 * @return - boolean if table and fields are created (Group table, group id in FEEDS, SUBSCRIPTION TABLES)
\r
554 @SuppressWarnings("resource")
\r
555 private boolean retroFit11() {
\r
556 final String[] expected_tables = {
\r
559 Connection c = null;
\r
562 // If expected tables are not present, then add new routing tables
\r
563 c = getConnection();
\r
564 Set<String> tables = getTableSet(c);
\r
565 boolean initialize = false;
\r
566 for (String s : expected_tables) {
\r
567 initialize |= !tables.contains(s);
\r
570 intlogger.info("PROV9002: Adding GROUPS table for Release 1610.");
\r
571 runInitScript(c, 4); // script 4 creates the routing tables
\r
574 // Add GROUPID column to FEEDS/SUBSCRIPTIONS
\r
575 DatabaseMetaData md = c.getMetaData();
\r
576 for (String tbl : new String[] {"FEEDS", "SUBSCRIPTIONS" }) {
\r
577 boolean add_col = true;
\r
578 ResultSet rs = md.getColumns("datarouter", "", tbl, "GROUPID");
\r
580 add_col = !rs.next();
\r
585 intlogger.info("PROV9002: Adding GROUPID column to "+tbl+" table.");
\r
586 Statement s = c.createStatement();
\r
587 s.execute("ALTER TABLE "+tbl+" ADD COLUMN GROUPID INT(10) UNSIGNED NOT NULL DEFAULT 0 AFTER FEEDID");
\r
591 } catch (SQLException e) {
\r
592 intlogger.fatal("PROV9000: The database credentials are not working: "+e.getMessage());
\r
603 * Copy the log table <i>table_name</i> to LOG_RECORDS;
\r
604 * @param table_name the name of the old (1.0.*) table to copy
\r
605 * @param table_class the class used to instantiate a record from the table
\r
606 * @throws SQLException if there is a problem getting a MySQL connection
\r
608 @SuppressWarnings("resource")
\r
609 private void copyLogTable(String table_name, Class<? extends Loadable> table_class) throws SQLException {
\r
610 long start = System.currentTimeMillis();
\r
612 Connection c1 = getConnection();
\r
613 Connection c2 = getConnection();
\r
616 Constructor<? extends Loadable> cnst = table_class.getConstructor(ResultSet.class);
\r
617 PreparedStatement ps = c2.prepareStatement(LogfileLoader.INSERT_SQL);
\r
618 Statement stmt = c1.createStatement();
\r
619 ResultSet rs = stmt.executeQuery("select * from "+table_name);
\r
620 while (rs.next()) {
\r
621 Loadable rec = cnst.newInstance(rs);
\r
623 ps.setLong(18, ++nextid);
\r
624 ps.executeUpdate();
\r
625 if ((++n % 10000) == 0)
\r
626 intlogger.debug(" "+n+" records done.");
\r
630 } catch (SQLException e) {
\r
631 e.printStackTrace();
\r
632 } catch (NoSuchMethodException e) {
\r
633 e.printStackTrace();
\r
634 } catch (SecurityException e) {
\r
635 e.printStackTrace();
\r
636 } catch (InstantiationException e) {
\r
637 e.printStackTrace();
\r
638 } catch (IllegalAccessException e) {
\r
639 e.printStackTrace();
\r
640 } catch (IllegalArgumentException e) {
\r
641 e.printStackTrace();
\r
642 } catch (InvocationTargetException e) {
\r
643 e.printStackTrace();
\r
648 long x = (System.currentTimeMillis() - start);
\r
649 intlogger.debug(" "+n+" records done in "+x+" ms.");
\r
653 * Get a set of all table names in the DB.
\r
654 * @param c a DB connection
\r
655 * @return the set of table names
\r
657 private Set<String> getTableSet(Connection c) {
\r
658 Set<String> tables = new HashSet<String>();
\r
660 DatabaseMetaData md = c.getMetaData();
\r
661 ResultSet rs = md.getTables("datarouter", "", "", null);
\r
663 while (rs.next()) {
\r
664 tables.add(rs.getString("TABLE_NAME"));
\r
668 } catch (SQLException e) {
\r
673 * Initialize the tables by running the initialization scripts located in the directory specified
\r
674 * by the property <i>org.onap.dmaap.datarouter.provserver.dbscripts</i>. Scripts have names of
\r
675 * the form mysql_init_NNNN.
\r
676 * @param c a DB connection
\r
677 * @param n the number of the mysql_init_NNNN script to run
\r
679 private void runInitScript(Connection c, int n) {
\r
680 String scriptdir = (String) props.get("org.onap.dmaap.datarouter.provserver.dbscripts");
\r
681 StringBuilder sb = new StringBuilder();
\r
683 String scriptfile = String.format("%s/mysql_init_%04d", scriptdir, n);
\r
684 if (!(new File(scriptfile)).exists())
\r
687 LineNumberReader in = new LineNumberReader(new FileReader(scriptfile));
\r
689 while ((line = in.readLine()) != null) {
\r
690 if (!line.startsWith("--")) {
\r
691 line = line.trim();
\r
693 if (line.endsWith(";")) {
\r
694 // Execute one DDL statement
\r
695 String sql = sb.toString();
\r
697 Statement s = c.createStatement();
\r
705 } catch (Exception e) {
\r
706 intlogger.fatal("PROV9002 Error when initializing table: "+e.getMessage());
\r