KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jivesoftware > database > DbConnectionManager


1 /**
2  * $RCSfile: DbConnectionManager.java,v $
3  * $Revision: 1.16 $
4  * $Date: 2005/07/03 20:53:01 $
5  *
6  * Copyright (C) 2004 Jive Software. All rights reserved.
7  *
8  * This software is published under the terms of the GNU Public License (GPL),
9  * a copy of which is included in this distribution.
10  */

11
12
13 package org.jivesoftware.database;
14
15 import org.jivesoftware.util.ClassUtils;
16 import org.jivesoftware.util.JiveGlobals;
17 import org.jivesoftware.util.Log;
18
19 import java.io.*;
20 import java.sql.*;
21
22 /**
23  * Central manager of database connections. All methods are static so that they
24  * can be easily accessed throughout the classes in the database package.<p>
25  * <p/>
26  * This class also provides a set of utility methods that abstract out
27  * operations that may not work on all databases such as setting the max number
28  * or rows that a query should return.
29  *
30  * @author Jive Software
31  *
32  * @see org.jivesoftware.database.ConnectionProvider
33  */

34 public class DbConnectionManager {
35
36      private static final String JavaDoc CHECK_VERSION =
37             "SELECT majorVersion, minorVersion FROM jiveVersion";
38
39     /**
40      * Database schema major version. The schema version corresponds to the
41      * product release version, but may not exactly match in the case that
42      * the product version has advanced without schema changes.
43      */

44     private static final int CURRENT_MAJOR_VERSION = 2;
45
46     /**
47      * Database schema minor version.
48      */

49     private static final int CURRENT_MINOR_VERSION = 2;
50
51     private static ConnectionProvider connectionProvider;
52     private static Object JavaDoc providerLock = new Object JavaDoc();
53
54     // True if connection profiling is turned on. Always false by default.
55
private static boolean profilingEnabled = false;
56
57     // True if the database support transactions.
58
private static boolean transactionsSupported;
59     // True if the database requires large text fields to be streamed.
60
private static boolean streamTextRequired;
61     // True if the database supports the Statement.setMaxRows() method.
62
private static boolean maxRowsSupported;
63     // True if the database supports the Statement.setFetchSize() method.
64
private static boolean fetchSizeSupported;
65     // True if the database supports correlated subqueries.
66
private static boolean subqueriesSupported;
67     // True if the database supports scroll-insensitive results.
68
private static boolean scrollResultsSupported;
69     // True if the database supports batch updates.
70
private static boolean batchUpdatesSupported;
71
72     private static DatabaseType databaseType = DatabaseType.unknown;
73
74     /**
75      * Returns a database connection from the currently active connection
76      * provider. (auto commit is set to true).
77      */

78     public static Connection getConnection() throws SQLException {
79         if (connectionProvider == null) {
80             synchronized (providerLock) {
81                 if (connectionProvider == null) {
82                     // Attempt to load the connection provider classname as
83
// a Jive property.
84
String JavaDoc className = JiveGlobals.getXMLProperty("connectionProvider.className");
85                     if (className != null) {
86                         // Attempt to load the class.
87
try {
88                             Class JavaDoc conClass = ClassUtils.forName(className);
89                             setConnectionProvider((ConnectionProvider)conClass.newInstance());
90                         }
91                         catch (Exception JavaDoc e) {
92                             Log.error("Warning: failed to create the " +
93                                     "connection provider specified by connection" +
94                                     "Provider.className. Using the default pool.", e);
95                             setConnectionProvider(new DefaultConnectionProvider());
96                         }
97                     }
98                     else {
99                         setConnectionProvider(new DefaultConnectionProvider());
100                     }
101                 }
102             }
103         }
104         Connection con = connectionProvider.getConnection();
105
106         if (con == null) {
107             Log.error("WARNING: ConnectionManager.getConnection() " +
108                     "failed to obtain a connection.");
109         }
110         // See if profiling is enabled. If yes, wrap the connection with a
111
// profiled connection.
112
if (profilingEnabled) {
113             return new ProfiledConnection(con);
114         }
115         else {
116             return con;
117         }
118     }
119
120     /**
121      * Returns a Connection from the currently active connection provider that
122      * is ready to participate in transactions (auto commit is set to false).
123      */

124     public static Connection getTransactionConnection() throws SQLException {
125         Connection con = getConnection();
126         if (isTransactionsSupported()) {
127             con.setAutoCommit(false);
128         }
129         return con;
130     }
131
132     /**
133      * Closes a Connection. However, it first rolls back the transaction or
134      * commits it depending on the value of <code>abortTransaction</code>.
135      */

136     public static void closeTransactionConnection(Connection con, boolean abortTransaction) {
137         // test to see if the connection passed in is null
138
if (con == null) {
139             return;
140         }
141
142         // Rollback or commit the transaction
143
if (isTransactionsSupported()) {
144             try {
145                 if (abortTransaction) {
146                     con.rollback();
147                 }
148                 else {
149                     con.commit();
150                 }
151             }
152             catch (Exception JavaDoc e) {
153                 Log.error(e);
154             }
155         }
156         try {
157             // Reset the connection to auto-commit mode.
158
if (isTransactionsSupported()) {
159                 con.setAutoCommit(true);
160             }
161         }
162         catch (Exception JavaDoc e) {
163             Log.error(e);
164         }
165         try {
166             // Close the db connection.
167
con.close();
168         }
169         catch (Exception JavaDoc e) {
170             Log.error(e);
171         }
172     }
173
174     /**
175      * Closes a prepared statement and database connection (returning the connection to
176      * the connection pool). This method should be called within the finally section of
177      * your database logic, as in the following example:
178      *
179      * <pre>
180      * Connection con = null;
181      * PrepatedStatment pstmt = null;
182      * try {
183      * con = ConnectionManager.getConnection();
184      * pstmt = con.prepareStatement("select * from blah");
185      * ....
186      * }
187      * catch (SQLException sqle) {
188      * Log.error(sqle);
189      * }
190      * finally {
191      * DbConnectionManager.closeConnection(pstmt, con);
192      * }</pre>
193      *
194      * @param pstmt the prepated statement.
195      * @param con the connection.
196      */

197     public static void closeConnection(PreparedStatement pstmt, Connection con) {
198         try {
199             if (pstmt != null) {
200                 pstmt.close();
201             }
202         }
203         catch (Exception JavaDoc e) {
204             Log.error(e);
205         }
206         closeConnection(con);
207     }
208
209     /**
210      * Closes a database connection (returning the connection to the connection pool). Any
211      * statements associated with the connection should be closed before calling this method.
212      * This method should be called within the finally section of your database logic, as
213      * in the following example:
214      *
215      * <pre>
216      * Connection con = null;
217      * try {
218      * con = ConnectionManager.getConnection();
219      * ....
220      * }
221      * catch (SQLException sqle) {
222      * Log.error(sqle);
223      * }
224      * finally {
225      * DbConnectionManager.closeConnection(con);
226      * }</pre>
227      *
228      * @param con the connection.
229      */

230     public static void closeConnection(Connection con) {
231         try {
232             if (con != null) {
233                 con.close();
234             }
235         }
236         catch (Exception JavaDoc e) {
237             Log.error(e);
238         }
239     }
240
241     /**
242      * Creates a scroll insensitive Statement if the JDBC driver supports it, or a normal
243      * Statement otherwise.
244      *
245      * @param con the database connection.
246      * @return a Statement
247      * @throws SQLException if an error occurs.
248      */

249     public static Statement createScrollableStatement(Connection con) throws SQLException {
250         if (isScrollResultsSupported()) {
251             return con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
252                     ResultSet.CONCUR_READ_ONLY);
253         }
254         else {
255             return con.createStatement();
256         }
257     }
258
259     /**
260      * Creates a scroll insensitive PreparedStatement if the JDBC driver supports it, or a normal
261      * PreparedStatement otherwise.
262      *
263      * @param con the database connection.
264      * @param sql the SQL to create the PreparedStatement with.
265      * @return a PreparedStatement
266      * @throws java.sql.SQLException if an error occurs.
267      */

268     public static PreparedStatement createScrollablePreparedStatement(Connection con, String JavaDoc sql)
269             throws SQLException {
270         if (isScrollResultsSupported()) {
271             return con.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE,
272                     ResultSet.CONCUR_READ_ONLY);
273         }
274         else {
275             return con.prepareStatement(sql);
276         }
277     }
278
279     /**
280      * Scrolls forward in a result set the specified number of rows. If the JDBC driver
281      * supports the feature, the cursor will be moved directly. Otherwise, we scroll
282      * through results one by one manually by calling <tt>rs.next()</tt>.
283      *
284      * @param rs the ResultSet object to scroll.
285      * @param rowNumber the row number to scroll forward to.
286      * @throws SQLException if an error occurs.
287      */

288     public static void scrollResultSet(ResultSet rs, int rowNumber) throws SQLException {
289         // If the driver supports scrollable result sets, use that feature.
290
if (isScrollResultsSupported()) {
291             if (rowNumber > 0) {
292                 rs.setFetchDirection(ResultSet.FETCH_FORWARD);
293                 rs.relative(rowNumber);
294             }
295         }
296         // Otherwise, manually scroll to the correct row.
297
else {
298             for (int i = 0; i < rowNumber; i++) {
299                 rs.next();
300             }
301         }
302     }
303
304     /**
305      * Returns the current connection provider. The only case in which this
306      * method should be called is if more information about the current
307      * connection provider is needed. Database connections should always be
308      * obtained by calling the getConnection method of this class.
309      */

310     public static ConnectionProvider getConnectionProvider() {
311         return connectionProvider;
312     }
313
314     /**
315      * Sets the connection provider. The old provider (if it exists) is shut
316      * down before the new one is started. A connection provider <b>should
317      * not</b> be started before being passed to the connection manager
318      * because the manager will call the start() method automatically.
319      *
320      * @param provider the ConnectionProvider that the manager should obtain
321      * connections from.
322      */

323     public static void setConnectionProvider(ConnectionProvider provider) {
324         synchronized (providerLock) {
325             if (connectionProvider != null) {
326                 connectionProvider.destroy();
327                 connectionProvider = null;
328             }
329             connectionProvider = provider;
330             connectionProvider.start();
331             // Now, get a connection to determine meta data.
332
Connection con = null;
333             try {
334                 con = connectionProvider.getConnection();
335                 setMetaData(con);
336
337                 // Check to see if the database schema needs to be upgraded.
338
try {
339                     upgradeDatabase(con);
340                 }
341                 catch (Exception JavaDoc e) {
342                     Log.error("Database upgrade failed. Please manually upgrade your database.", e);
343                     System.out.println("Database upgrade failed. Please manually upgrade your " +
344                             "database.");
345                 }
346             }
347             catch (Exception JavaDoc e) {
348                 Log.error(e);
349             }
350             finally {
351                 try { if (con != null) { con.close(); } }
352                 catch (Exception JavaDoc e) { Log.error(e); }
353             }
354         }
355         // Remember what connection provider we want to use for restarts.
356
JiveGlobals.setXMLProperty("connectionProvider.className", provider.getClass().getName());
357     }
358
359     /**
360      * Retrives a large text column from a result set, automatically performing
361      * streaming if the JDBC driver requires it. This is necessary because
362      * different JDBC drivers have different capabilities and methods for
363      * retrieving large text values.
364      *
365      * @param rs the ResultSet to retrieve the text field from.
366      * @param columnIndex the column in the ResultSet of the text field.
367      * @return the String value of the text field.
368      */

369     public static String JavaDoc getLargeTextField(ResultSet rs, int columnIndex) throws SQLException {
370         if (isStreamTextRequired()) {
371             Reader bodyReader = null;
372             String JavaDoc value = null;
373             try {
374                 bodyReader = rs.getCharacterStream(columnIndex);
375                 if (bodyReader == null) {
376                     return null;
377                 }
378                 char[] buf = new char[256];
379                 int len;
380                 StringWriter out = new StringWriter(256);
381                 while ((len = bodyReader.read(buf)) >= 0) {
382                     out.write(buf, 0, len);
383                 }
384                 value = out.toString();
385                 out.close();
386             }
387             catch (Exception JavaDoc e) {
388                 Log.error(e);
389                 throw new SQLException("Failed to load text field");
390             }
391             finally {
392                 try {
393                     bodyReader.close();
394                 }
395                 catch (Exception JavaDoc e) {
396                 }
397             }
398             return value;
399         }
400         else {
401             return rs.getString(columnIndex);
402         }
403     }
404
405     /**
406      * Sets a large text column in a result set, automatically performing
407      * streaming if the JDBC driver requires it. This is necessary because
408      * different JDBC drivers have different capabilities and methods for
409      * setting large text values.
410      *
411      * @param pstmt the PreparedStatement to set the text field in.
412      * @param parameterIndex the index corresponding to the text field.
413      * @param value the String to set.
414      */

415     public static void setLargeTextField(PreparedStatement pstmt, int parameterIndex,
416             String JavaDoc value) throws SQLException
417     {
418         if (isStreamTextRequired()) {
419             Reader bodyReader = null;
420             try {
421                 bodyReader = new StringReader(value);
422                 pstmt.setCharacterStream(parameterIndex, bodyReader, value.length());
423             }
424             catch (Exception JavaDoc e) {
425                 Log.error(e);
426                 throw new SQLException("Failed to set text field.");
427             }
428             // Leave bodyReader open so that the db can read from it. It *should*
429
// be garbage collected after it's done without needing to call close.
430
}
431         else {
432             pstmt.setString(parameterIndex, value);
433         }
434     }
435
436     /**
437      * Sets the max number of rows that should be returned from executing a
438      * statement. The operation is automatically bypassed if Jive knows that the
439      * the JDBC driver or database doesn't support it.
440      *
441      * @param stmt the Statement to set the max number of rows for.
442      * @param maxRows the max number of rows to return.
443      */

444     public static void setMaxRows(Statement stmt, int maxRows) {
445         if (isMaxRowsSupported()) {
446             try {
447                 stmt.setMaxRows(maxRows);
448             }
449             catch (Throwable JavaDoc t) {
450                 // Ignore. Exception may happen if the driver doesn't support
451
// this operation and we didn't set meta-data correctly.
452
// However, it is a good idea to update the meta-data so that
453
// we don't have to incur the cost of catching an exception
454
// each time.
455
maxRowsSupported = false;
456             }
457         }
458     }
459
460     /**
461      * Sets the number of rows that the JDBC driver should buffer at a time.
462      * The operation is automatically bypassed if Jive knows that the
463      * the JDBC driver or database doesn't support it.
464      *
465      * @param rs the ResultSet to set the fetch size for.
466      * @param fetchSize the fetchSize.
467      */

468     public static void setFetchSize(ResultSet rs, int fetchSize) {
469         if (isFetchSizeSupported()) {
470             try {
471                 rs.setFetchSize(fetchSize);
472             }
473             catch (Throwable JavaDoc t) {
474                 // Ignore. Exception may happen if the driver doesn't support
475
// this operation and we didn't set meta-data correctly.
476
// However, it is a good idea to update the meta-data so that
477
// we don't have to incur the cost of catching an exception
478
// each time.
479
fetchSizeSupported = false;
480             }
481         }
482     }
483
484     /**
485      * Uses a connection from the database to set meta data information about
486      * what different JDBC drivers and databases support.
487      */

488     private static void setMetaData(Connection con) throws SQLException {
489         DatabaseMetaData metaData = con.getMetaData();
490         // Supports transactions?
491
transactionsSupported = metaData.supportsTransactions();
492         // Supports subqueries?
493
subqueriesSupported = metaData.supportsCorrelatedSubqueries();
494         // Supports scroll insensitive result sets? Try/catch block is a
495
// workaround for DB2 JDBC driver, which throws an exception on
496
// the method call.
497
try {
498             scrollResultsSupported = metaData.supportsResultSetType(
499                     ResultSet.TYPE_SCROLL_INSENSITIVE);
500         }
501         catch (Exception JavaDoc e) {
502             scrollResultsSupported = false;
503         }
504         // Supports batch updates
505
batchUpdatesSupported = metaData.supportsBatchUpdates();
506
507         // Set defaults for other meta properties
508
streamTextRequired = false;
509         maxRowsSupported = true;
510         fetchSizeSupported = true;
511
512         // Get the database name so that we can perform meta data settings.
513
String JavaDoc dbName = metaData.getDatabaseProductName().toLowerCase();
514         String JavaDoc driverName = metaData.getDriverName().toLowerCase();
515
516         // Oracle properties.
517
if (dbName.indexOf("oracle") != -1) {
518             databaseType = DatabaseType.oracle;
519             streamTextRequired = true;
520             scrollResultsSupported = false;
521             // The i-net AUGURO JDBC driver
522
if (driverName.indexOf("auguro") != -1) {
523                 streamTextRequired = false;
524                 fetchSizeSupported = true;
525                 maxRowsSupported = false;
526             }
527         }
528         // Postgres properties
529
else if (dbName.indexOf("postgres") != -1) {
530             databaseType = DatabaseType.postgres;
531             // Postgres blows, so disable scrolling result sets.
532
scrollResultsSupported = false;
533             fetchSizeSupported = false;
534         }
535         // Interbase properties
536
else if (dbName.indexOf("interbase") != -1) {
537             databaseType = DatabaseType.interbase;
538             fetchSizeSupported = false;
539             maxRowsSupported = false;
540         }
541         // SQLServer, JDBC driver i-net UNA properties
542
else if (dbName.indexOf("sql server") != -1 &&
543                 driverName.indexOf("una") != -1)
544         {
545             databaseType = DatabaseType.sqlserver;
546             fetchSizeSupported = true;
547             maxRowsSupported = false;
548         }
549         // MySQL properties
550
else if (dbName.indexOf("mysql") != -1) {
551             databaseType = DatabaseType.mysql;
552             transactionsSupported = false;
553         }
554         // HSQL properties
555
else if (dbName.indexOf("hsql") != -1) {
556             databaseType = DatabaseType.hsqldb;
557             scrollResultsSupported = false;
558         }
559         // DB2 properties.
560
else if (dbName.indexOf("db2") != 1) {
561             databaseType = DatabaseType.db2;
562         }
563     }
564
565     /**
566      * Returns the database type. The possible types are constants of the
567      * DatabaseType class. Any database that doesn't have its own constant
568      * falls into the "Other" category.
569      *
570      * @return the database type.
571      */

572     public static DatabaseType getDatabaseType() {
573         return databaseType;
574     }
575
576     /**
577      * Returns true if connection profiling is turned on. You can collect
578      * profiling statistics by using the static methods of the ProfiledConnection
579      * class.
580      *
581      * @return true if connection profiling is enabled.
582      */

583     public static boolean isProfilingEnabled() {
584         return profilingEnabled;
585     }
586
587     /**
588      * Turns connection profiling on or off. You can collect profiling
589      * statistics by using the static methods of the ProfiledConnection
590      * class.
591      *
592      * @param enable true to enable profiling; false to disable.
593      */

594     public static void setProfilingEnabled(boolean enable) {
595         // If enabling profiling, call the start method on ProfiledConnection
596
if (!profilingEnabled && enable) {
597             ProfiledConnection.start();
598         }
599         // Otherwise, if turning off, call stop method.
600
else if (profilingEnabled && !enable) {
601             ProfiledConnection.stop();
602         }
603         profilingEnabled = enable;
604     }
605
606     public static boolean isTransactionsSupported() {
607         return transactionsSupported;
608     }
609
610     public static boolean isStreamTextRequired() {
611         return streamTextRequired;
612     }
613
614     public static boolean isMaxRowsSupported() {
615         return maxRowsSupported;
616     }
617
618     public static boolean isFetchSizeSupported() {
619
620         return fetchSizeSupported;
621     }
622
623     public static boolean isSubqueriesSupported() {
624         return subqueriesSupported;
625     }
626
627     public static boolean isScrollResultsSupported() {
628         return scrollResultsSupported;
629     }
630
631     public static boolean isBatchUpdatesSupported() {
632         return batchUpdatesSupported;
633     }
634
635     /**
636      * A class that identifies the type of the database that Jive is connected
637      * to. In most cases, we don't want to make any database specific calls
638      * and have no need to know the type of database we're using. However,
639      * there are certain cases where it's critical to know the database for
640      * performance reasons.
641      */

642     public static enum DatabaseType {
643
644         oracle,
645
646         postgres,
647
648         mysql,
649
650         hsqldb,
651
652         db2,
653
654         sqlserver,
655
656         interbase,
657
658         unknown;
659     }
660
661     /**
662      * Checks to see if the database needs to be upgraded. This method should be
663      * called once every time the application starts up.
664      *
665      * @throws SQLException if an error occured.
666      */

667     private static boolean upgradeDatabase(Connection con) throws Exception JavaDoc {
668         int majorVersion;
669         int minorVersion;
670         PreparedStatement pstmt = null;
671         try {
672             pstmt = con.prepareStatement(CHECK_VERSION);
673             ResultSet rs = pstmt.executeQuery();
674             // If no results, assume the version is 2.0.
675
if (!rs.next()) {
676                 majorVersion = 2;
677                 minorVersion = 0;
678             }
679             majorVersion = rs.getInt(1);
680             minorVersion = rs.getInt(2);
681             rs.close();
682         }
683         catch (SQLException sqle) {
684             // If the table doesn't exist, an error will be thrown. Therefore
685
// assume the version is 2.0.
686
majorVersion = 2;
687             minorVersion = 0;
688         }
689         finally {
690             try { if (pstmt != null) { pstmt.close(); } }
691             catch (Exception JavaDoc e) { Log.error(e); }
692         }
693         if (majorVersion == CURRENT_MAJOR_VERSION && minorVersion == CURRENT_MINOR_VERSION) {
694             return false;
695         }
696         // The database is an old version that needs to be upgraded.
697
Log.info("Found old database schema (" + majorVersion + "." + minorVersion + "). " +
698                 "Upgrading to latest schema.");
699         System.out.println("Found old database schema (" + majorVersion + "." +
700                 minorVersion + "). " + "Upgrading to latest schema.");
701         if (databaseType == DatabaseType.unknown) {
702             Log.info("Warning: database type unknown. You must manually upgrade your database.");
703             System.out.println("Warning: database type unknown. You must manually upgrade your " +
704                     "database.");
705             return false;
706         }
707         else if (databaseType == DatabaseType.interbase) {
708             Log.info("Warning: automatic upgrades of Interbase are not supported. You " +
709                     "must manually upgrade your database.");
710             System.out.println("Warning: automatic upgrades of Interbase are not supported. You " +
711                     "must manually upgrade your database.");
712             return false;
713         }
714         // Run all upgrade scripts until we're up to the latest schema.
715
for (int i=minorVersion; i<CURRENT_MINOR_VERSION; i++) {
716             BufferedReader in = null;
717             Statement stmt = null;
718             try {
719                 // Resource will be like "/database/upgrade/2.0_to_2.1/messenger_hsqldb.sql"
720
String JavaDoc resourceName = "/database/upgrade/" + CURRENT_MAJOR_VERSION + "." + i +
721                         "_to_" + CURRENT_MAJOR_VERSION + "." + (i+1) + "/messenger_" +
722                         databaseType + ".sql";
723                 in = new BufferedReader(new InputStreamReader(
724                         new DbConnectionManager().getClass().getResourceAsStream(resourceName)));
725                 boolean done = false;
726                 while (!done) {
727                     StringBuilder JavaDoc command = new StringBuilder JavaDoc();
728                     while (true) {
729                         String JavaDoc line = in.readLine();
730                         if (line == null) {
731                             done = true;
732                             break;
733                         }
734                         // Ignore comments and blank lines.
735
if (isSQLCommandPart(line)) {
736                             command.append(line);
737                         }
738                         if (line.endsWith(";")) {
739                             break;
740                         }
741                     }
742                     // Send command to database.
743
if (!done && command != null) {
744                         stmt = con.createStatement();
745                         stmt.execute(command.toString());
746                         stmt.close();
747                     }
748                 }
749             }
750             finally {
751                 try { if (pstmt != null) { pstmt.close(); } }
752                 catch (Exception JavaDoc e) { Log.error(e); }
753                 if (in != null) {
754                     try { in.close(); }
755                     catch (Exception JavaDoc e) { }
756                 }
757             }
758         }
759         Log.info("Database upgraded successfully.");
760         System.out.println("Database upgraded successfully.");
761         return true;
762     }
763
764     /**
765      * Returns true if a line from a SQL schema is a valid command part.
766      *
767      * @param line the line of the schema.
768      * @return true if a valid command part.
769      */

770     public static boolean isSQLCommandPart(String JavaDoc line) {
771         line = line.trim();
772         if (line.equals("")) {
773             return false;
774         }
775         // Check to see if the line is a comment. Valid comment types:
776
// "//" is HSQLDB
777
// "--" is DB2 and Postgres
778
// "#" is MySQL
779
// "REM" is Oracle
780
// "/*" is SQLServer
781
if (line.startsWith("//") || line.startsWith("--") || line.startsWith("#") ||
782                 line.startsWith("REM") || line.startsWith("/*"))
783         {
784             return false;
785         }
786         return true;
787     }
788
789     private DbConnectionManager() {
790         // Not instantiable.
791
}
792 }
Popular Tags