KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > continuent > sequoia > driver > Driver


1 /**
2  * Sequoia: Database clustering technology.
3  * Copyright (C) 2002-2004 French National Institute For Research In Computer
4  * Science And Control (INRIA).
5  * Copyright (C) 2005 AmicoSoft, Inc. dba Emic Networks
6  * Copyright (C) 2005-2006 Continuent, Inc.
7  * Contact: sequoia@continuent.org
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  * Initial developer(s): Emmanuel Cecchet.
22  * Contributor(s): Julie Marguerite, Mathieu Peltier, Marek Prochazka, Sara
23  * Bouchenak, Jaco Swart.
24  */

25
26 package org.continuent.sequoia.driver;
27
28 import java.io.IOException JavaDoc;
29 import java.net.Socket JavaDoc;
30 import java.sql.DriverPropertyInfo JavaDoc;
31 import java.sql.SQLException JavaDoc;
32 import java.util.ArrayList JavaDoc;
33 import java.util.HashMap JavaDoc;
34 import java.util.Iterator JavaDoc;
35 import java.util.Properties JavaDoc;
36
37 import javax.net.SocketFactory;
38
39 import org.continuent.sequoia.common.exceptions.AuthenticationException;
40 import org.continuent.sequoia.common.exceptions.NoMoreControllerException;
41 import org.continuent.sequoia.common.exceptions.driver.DriverSQLException;
42 import org.continuent.sequoia.common.net.SSLConfiguration;
43 import org.continuent.sequoia.common.net.SocketFactoryFactory;
44 import org.continuent.sequoia.common.protocol.Commands;
45 import org.continuent.sequoia.common.stream.DriverBufferedInputStream;
46 import org.continuent.sequoia.common.stream.DriverBufferedOutputStream;
47 import org.continuent.sequoia.common.util.Constants;
48
49 /**
50  * Sequoia Driver for client side. This driver is a generic driver that is
51  * designed to replace any specific JDBC driver that could be used by a client.
52  * The client only has to know the node where the Sequoia controller is running
53  * and the database he wants to access (the RDBMS could be PostgreSQL, Oracle,
54  * DB2, Sybase, MySQL or whatever, we only need the name of the database and the
55  * Sequoia controller will be responsible for finding the RDBMs hosting this
56  * database).
57  * <p>
58  * The Sequoia driver can be loaded from the client with:
59  * <code>Class.forName("org.continuent.sequoia.driver.Driver");</code>
60  * <p>
61  * The URL expected for the use with Sequoia is:
62  * <code>jdbc:sequoia://host1:port1,host2:port2/database</code>.
63  * <p>
64  * At least one host must be specified. If several hosts are given, one is
65  * picked up randomly from the list. If the currently selected controller fails,
66  * another one is automatically picked up from the list.
67  * <p>
68  * Default port number is 25322 if omitted.
69  * <p>
70  * Those 2 examples are equivalent:
71  *
72  * <pre>
73  * DriverManager.getConnection(&quot;jdbc:sequoia://localhost:/tpcw&quot;);
74  * DriverManager.getConnection(&quot;jdbc:sequoia://localhost:25322/tpcw&quot;);
75  * </pre>
76  *
77  * <p>
78  * Examples using 2 controllers for fault tolerance:
79  *
80  * <pre>
81  * DriverManager
82  * .getConnection(&quot;jdbc:sequoia://cluster1.continuent.org:25322,cluster2.continuent.org:25322/tpcw&quot;);
83  * DriverManager
84  * .getConnection(&quot;jdbc:sequoia://localhost:25322,remote.continuent.org:25322/tpcw&quot;);
85  * DriverManager
86  * .getConnection(&quot;jdbc:sequoia://smpnode.com:25322,smpnode.com:1098/tpcw&quot;);
87  * </pre>
88  *
89  * <p>
90  * The driver accepts a number of options that starts after a ? sign and are
91  * separated by an & sign. Each option is a name=value pair. Example:
92  * jdbc:sequoia://host/db?option1=value1;option2=value2.
93  * <p>
94  * Currently supported options are:
95  *
96  * <pre>
97  * user: user login
98  * password: user password
99  * ssl: set this to true to use SSL encrypted connections
100  * sslKeyStore: defines the key store to use for SSL connections
101  * sslKeyStorePassword: defines the key store password for SSL connections
102  * sslTrustStore: defines the trust store to use for SSL connections
103  * sslTrustStorePassword: defines the trust store password for SSL connections
104  * escapeBackslash: set this to true to escape backslashes when performing escape processing of PreparedStatements
105  * escapeSingleQuote: set this to true to escape single quotes (') when performing escape processing of PreparedStatements
106  * escapeCharacter: use this character to prepend and append to the values when performing escape processing of PreparedStatements
107  * connectionPooling: set this to false if you do not want the driver to perform transparent connection pooling
108  * preferredController: defines the strategy to use to choose a preferred controller to connect to
109  * - jdbc:sequoia://node1,node2,node3/myDB?preferredController=ordered
110  * Always connect to node1, and if not available then try to node2 and
111  * finally if none are available try node3.
112  * - jdbc:sequoia://node1,node2,node3/myDB?preferredController=random
113  * Pickup a controller node randomly (default strategy)
114  * - jdbc:sequoia://node1,node2:25343,node3/myDB?preferredController=node2:25343,node3
115  * Round-robin between node2 and node3, fallback to node1 if none of node2
116  * and node3 is available.
117  * - jdbc:sequoia://node1,node2,node3/myDB?preferredController=roundRobin
118  * Round robin starting with first node in URL.
119  * retryIntervalInMs: once a controller has died, the driver will try to
120  * reconnect to this controller every retryIntervalInMs to see if the backend
121  * is back online. The default is 5000 (5 seconds).
122  * persistentConnection: defines if a connection should remain persistent on
123  * cluster backends between connection opening and closing (bypasses any
124  * connection pooling and preserve all information relative to the connection
125  * context. Default is false.
126  * retrieveSQLWarnings: set this to true if you want the controller to retrieve
127  * SQL warnings. Default is false, which means that (Connection|Statement|ResultSet).getWarnings()
128  * will always return null.
129  * allowCommitWithAutoCommit: When set to true, trying to call commit/rollback
130  * on a connection in autoCommit will not throw an exception. If set to false
131  * (default) an SQLException will be thrown when commit is called on a
132  * connection in autoCommit mode.
133  * alwaysGetGeneratedKeys: when set to true, always fetch generated keys even if
134  * not requested with Statement.RETURN_GENERATED_KEYS.
135  * </pre>
136  *
137  * <p>
138  * The first revision of the C-JDBC driver was inspired from the PostgreSQL JDBC
139  * driver by Peter T. Mount <peter@retep.org.uk>and the MM MySQL JDBC Drivers
140  * from Mark Matthews <mmatthew@worldserver.com>.
141  *
142  * @author <a HREF="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
143  * @author <a HREF="mailto:Julie.Marguerite@inria.fr">Julie Marguerite </a>
144  * @author <a HREF="mailto:Mathieu.Peltier@inrialpes.fr">Mathieu Peltier </a>
145  * @author <a HREF="mailto:Marek.Prochazka@inrialpes.fr">Marek Prochazka </a>
146  * @author <a HREF="mailto:Nicolas.Modrzyk@inrialpes.fr">Nicolas Modrzyk </a>
147  * @author <a HREF="mailto:jaco.swart@iblocks.co.uk">Jaco Swart </a>
148  * @version 1.0
149  */

150
151 public class Driver implements java.sql.Driver JavaDoc
152 {
153   /** Sequoia URL header. */
154   protected String JavaDoc sequoiaUrlHeader = "jdbc:sequoia://";
155
156   /** Sequoia URL header length. */
157   protected int sequoiaUrlHeaderLength = sequoiaUrlHeader
158                                                                                        .length();
159   /**
160    * Default interval in milliseconds before retrying to re-connect to a
161    * controller that has failed (default is 5 seconds or 5000 milliseconds)
162    */

163   public static final long DEFAULT_RETRY_INTERVAL_IN_MS = 5000;
164
165   /**
166    * List of driver properties initialized in the static class initializer
167    * <p>
168    * !!! Static intializer needs to be udpated when new properties are added !!!
169    */

170   protected static ArrayList JavaDoc driverPropertiesNames;
171
172   /** Sequoia driver property name (if you add one, read driverProperties above). */
173   protected static final String JavaDoc HOST_PROPERTY = "HOST";
174   protected static final String JavaDoc PORT_PROPERTY = "PORT";
175   protected static final String JavaDoc DATABASE_PROPERTY = "DATABASE";
176   protected static final String JavaDoc USER_PROPERTY = "user";
177   protected static final String JavaDoc PASSWORD_PROPERTY = "password";
178   protected static final String JavaDoc SSL_PROPERTY = "ssl";
179   protected static final String JavaDoc SSL_KEY_STORE_PROPERTY = "sslKeyStore";
180   protected static final String JavaDoc SSL_KEY_STORE_PASSWORD_PROPERTY = "sslKeyStorePassword";
181   protected static final String JavaDoc SSL_TRUST_STORE_PROPERTY = "sslTrustStore";
182   protected static final String JavaDoc SSL_TRUST_STORE_PASSWORD_PROPERTY = "sslTrustStorePassword";
183
184   protected static final String JavaDoc ESCAPE_BACKSLASH_PROPERTY = "escapeBackslash";
185   protected static final String JavaDoc ESCAPE_SINGLE_QUOTE_PROPERTY = "escapeSingleQuote";
186   protected static final String JavaDoc ESCAPE_CHARACTER_PROPERTY = "escapeCharacter";
187   protected static final String JavaDoc CONNECTION_POOLING_PROPERTY = "connectionPooling";
188   protected static final String JavaDoc PREFERRED_CONTROLLER_PROPERTY = "preferredController";
189   protected static final String JavaDoc RETRY_INTERVAL_IN_MS_PROPERTY = "retryIntervalInMs";
190   protected static final String JavaDoc DEBUG_PROPERTY = "debugLevel";
191   protected static final String JavaDoc PERSISTENT_CONNECTION_PROPERTY = "persistentConnection";
192   protected static final String JavaDoc RETRIEVE_SQL_WARNINGS_PROPERTY = "retrieveSQLWarnings";
193   protected static final String JavaDoc ALLOW_COMMIT_WTIH_AUTOCOMMIT_PROPERTY = "allowCommitWithAutoCommit";
194   protected static final String JavaDoc ALWAYS_RETRIEVE_GENERATED_KEYS_PROPERTY = "alwaysGetGeneratedKeys";
195
196   /** Sequoia driver property description. */
197   private static final String JavaDoc HOST_PROPERTY_DESCRIPTION = "Hostname of Sequoia controller";
198   private static final String JavaDoc PORT_PROPERTY_DESCRIPTION = "Port number of Sequoia controller";
199   private static final String JavaDoc DATABASE_PROPERTY_DESCRIPTION = "Database name";
200   private static final String JavaDoc USER_PROPERTY_DESCRIPTION = "Username to authenticate as";
201   private static final String JavaDoc PASSWORD_PROPERTY_DESCRIPTION = "Password to use for authentication";
202   private static final String JavaDoc SSL_PROPERTY_DESCRIPTION = "Set this to true to use SSL encrypted connections";
203   private static final String JavaDoc SSL_KEY_STORE_PROPERTY_DESCRIPTION = "Defines the key store to use for SSL connections";
204   private static final String JavaDoc SSL_KEY_STORE_PASSWORD_PROPERTY_DESCRIPTION = "Defines the key store password for SSL connections";
205   private static final String JavaDoc SSL_TRUST_STORE_PROPERTY_DESCRIPTION = "Defines the trust store to use for SSL connections";
206   private static final String JavaDoc SSL_TRUST_STORE_PASSWORD_PROPERTY_DESCRIPTION = "Defines the trust store password for SSL connections";
207   private static final String JavaDoc ESCAPE_BACKSLASH_PROPERTY_DESCRIPTION = "Set this to true to escape backslashes when performing escape processing of PreparedStatements";
208   private static final String JavaDoc ESCAPE_SINGLE_QUOTE_PROPERTY_DESCRIPTION = "Set this to true to escape single quotes (') when performing escape processing of PreparedStatements";
209   private static final String JavaDoc ESCAPE_CHARACTER_PROPERTY_DESCRIPTION = "Use this character to prepend and append to the values when performing escape processing of PreparedStatements";
210   protected static final String JavaDoc CONNECTION_POOLING_PROPERTY_DESCRIPTION = "Set this to false if you do not want the driver to perform transparent connection pooling";
211   protected static final String JavaDoc PREFERRED_CONTROLLER_PROPERTY_DESCRIPTION = "Defines the strategy to use to choose a preferred controller to connect to";
212   protected static final String JavaDoc RETRY_INTERVAL_IN_MS_PROPERTY_DESCRIPTION = "Interval in milliseconds before retrying to re-connect to a controller that has failed";
213   protected static final String JavaDoc DEBUG_PROPERTY_DESCRIPTION = "Debug level that can be set to 'debug', 'info' or 'off'";
214   protected static final String JavaDoc PERSISTENT_CONNECTION_PROPERTY_DESCRIPTION = "Defines if a connection in autoCommit mode should remain persistent on cluster backends";
215   protected static final String JavaDoc RETRIEVE_SQL_WARNINGS_PROPERTY_DESCRIPTION = "Set this to true to allow retrieval of SQL warnings. A value set to false will make *.getWarnings() always return null";
216   protected static final String JavaDoc ALLOW_COMMIT_WITH_AUTOCOMMIT_PROPERTY_DESCRIPTION = "Indicates whether or not commit can be called while autocommit is enabled";
217   protected static final String JavaDoc ALWAYS_RETRIEVE_GENERATED_KEYS_DESCRIPTION = "Indicates whether or not every INSERT should make generated keys available, if any";
218
219   /** Driver major version. */
220   public static final int MAJOR_VERSION = Constants
221                                                                                        .getMajorVersion();
222
223   /** Driver minor version. */
224   public static final int MINOR_VERSION = Constants
225                                                                                        .getMinorVersion();
226   /**
227    * Get the sequoia.ssl.enabled system property to check if SSL is enabled
228    *
229    * @deprecated since 3.0, prefer url option instead
230    */

231   protected static final boolean SSL_ENABLED_PROPERTY = "true"
232                                                                                        .equalsIgnoreCase(System
233                                                                                            .getProperty("sequoia.ssl.enabled"));
234
235   /**
236    * Cache of parsed URLs used to connect to the controller. It always grows and
237    * is never purged: we don't yet handle the unlikely case of a long-lived
238    * driver using zillions of different URLs. Warning: this caches urls BOTH
239    * with AND without properties.
240    * <p>
241    * Hashmap is URL=> <code>SequoiaUrl</code>
242    */

243   private HashMap JavaDoc parsedUrlsCache = new HashMap JavaDoc();
244
245   /** List of connections that are ready to be closed. */
246   protected ArrayList JavaDoc pendingConnectionClosing = new ArrayList JavaDoc();
247   protected boolean connectionClosingThreadisAlive = false;
248
249   private JDBCRegExp jdbcRegExp = new SequoiaJDBCRegExp();
250
251   // The static initializer registers ourselves with the DriverManager
252
// and try to bind the Sequoia Controller
253
static
254   {
255     // Register with the DriverManager (see JDBC API Tutorial and Reference,
256
// Second Edition p. 941)
257
try
258     {
259       java.sql.DriverManager.registerDriver(new Driver());
260     }
261     catch (SQLException JavaDoc e)
262     {
263       throw new RuntimeException JavaDoc("Unable to register Sequoia driver");
264     }
265
266     // Build the static list of driver properties
267
driverPropertiesNames = new ArrayList JavaDoc();
268     driverPropertiesNames.add(Driver.HOST_PROPERTY);
269     driverPropertiesNames.add(Driver.PORT_PROPERTY);
270     driverPropertiesNames.add(Driver.DATABASE_PROPERTY);
271     driverPropertiesNames.add(Driver.USER_PROPERTY);
272     driverPropertiesNames.add(Driver.PASSWORD_PROPERTY);
273     driverPropertiesNames.add(Driver.SSL_PROPERTY);
274     driverPropertiesNames.add(Driver.SSL_KEY_STORE_PROPERTY);
275     driverPropertiesNames.add(Driver.SSL_KEY_STORE_PASSWORD_PROPERTY);
276     driverPropertiesNames.add(Driver.SSL_TRUST_STORE_PROPERTY);
277     driverPropertiesNames.add(Driver.SSL_TRUST_STORE_PASSWORD_PROPERTY);
278
279     driverPropertiesNames.add(Driver.ESCAPE_BACKSLASH_PROPERTY);
280     driverPropertiesNames.add(Driver.ESCAPE_SINGLE_QUOTE_PROPERTY);
281     driverPropertiesNames.add(Driver.ESCAPE_CHARACTER_PROPERTY);
282     driverPropertiesNames.add(Driver.CONNECTION_POOLING_PROPERTY);
283     driverPropertiesNames.add(Driver.PREFERRED_CONTROLLER_PROPERTY);
284     driverPropertiesNames.add(Driver.RETRY_INTERVAL_IN_MS_PROPERTY);
285     driverPropertiesNames.add(Driver.DEBUG_PROPERTY);
286     driverPropertiesNames.add(Driver.PERSISTENT_CONNECTION_PROPERTY);
287     driverPropertiesNames.add(Driver.ALLOW_COMMIT_WTIH_AUTOCOMMIT_PROPERTY);
288     driverPropertiesNames.add(Driver.ALWAYS_RETRIEVE_GENERATED_KEYS_PROPERTY);
289   }
290
291   /**
292    * Asks the Sequoia controller if the requested database can be accessed with
293    * the provided user name and password. If the Sequoia controller can't access
294    * the requested database, an <code>SQLException</code> is thrown, else a
295    * "fake" <code>Connection</code> is returned to the user so that he or she
296    * can create <code>Statements</code>.
297    *
298    * @param url the URL of the Sequoia controller to which to connect.
299    * @param clientProperties a list of arbitrary string tag/value pairs as
300    * connection arguments (usually at least a "user" and "password").
301    * In case of conflict, this list overrides settings from the url;
302    * see SEQUOIA-105
303    * @return a <code>Connection</code> object that represents a connection to
304    * the database through the Sequoia Controller.
305    * @exception SQLException if an error occurs.
306    */

307   public java.sql.Connection JavaDoc connect(String JavaDoc url, Properties JavaDoc clientProperties)
308       throws SQLException JavaDoc
309   {
310     if (url == null)
311       throw new SQLException JavaDoc("Invalid null URL in connect");
312
313     /**
314      * If the URL is for another driver we must return null according to the
315      * javadoc of the implemented interface. This is likely to happen as the
316      * DriverManager tries every driver until one succeeds.
317      */

318     if (!url.startsWith(sequoiaUrlHeader))
319       return null;
320
321     Properties JavaDoc filteredProperties = filterProperties(clientProperties);
322
323     String JavaDoc urlCacheKey = url + filteredProperties.toString();
324
325     // In the common case, we do not synchronize
326
SequoiaUrl sequoiaUrl = (SequoiaUrl) parsedUrlsCache.get(urlCacheKey);
327     if (sequoiaUrl == null) // Not in the cache
328
{
329       synchronized (this)
330       {
331         // Recheck here in case someone updated before we entered the
332
// synchronized block
333
sequoiaUrl = (SequoiaUrl) parsedUrlsCache.get(urlCacheKey);
334         if (sequoiaUrl == null)
335         {
336           sequoiaUrl = new SequoiaUrl(this, url, filteredProperties);
337           parsedUrlsCache.put(urlCacheKey, sequoiaUrl);
338         }
339       }
340     }
341
342     ControllerInfo controller = null;
343     try
344     {
345       // Choose a controller according to the policy
346
controller = sequoiaUrl.getControllerConnectPolicy().getController();
347       return connectToController(sequoiaUrl, controller);
348     }
349     catch (AuthenticationException e)
350     {
351       throw (SQLException JavaDoc) new SQLException JavaDoc(e.getMessage()).initCause(e);
352     }
353     catch (NoMoreControllerException e)
354     {
355       throw (SQLException JavaDoc) new SQLException JavaDoc(
356           "No controller is available to accept connections").initCause(e);
357     }
358     catch (SQLException JavaDoc e)
359     {
360       // Add controller to suspect list
361
if (controller != null)
362       {
363         sequoiaUrl.getControllerConnectPolicy().suspectControllerOfFailure(
364             controller);
365         // Retry
366
return connect(url, filteredProperties);
367       }
368       else
369         throw e;
370     }
371     catch (RuntimeException JavaDoc e)
372     {
373       e.printStackTrace();
374       throw (SQLException JavaDoc) new SQLException JavaDoc(
375           "Unable to connect to the virtual database - Unexpected runtime error ("
376               + e + ")").initCause(e);
377     }
378   }
379
380   /**
381    * Connect to the given controller with the specified parameters.
382    *
383    * @param sequoiaUrl Sequoia URL object including parameters
384    * @param controller the controller to connect to
385    * @return the connection to the controller
386    * @throws AuthenticationException if the authentication has failed or the
387    * database name is wrong
388    * @throws DriverSQLException if the connection cannot be established with the
389    * controller
390    */

391   protected java.sql.Connection JavaDoc connectToController(SequoiaUrl sequoiaUrl,
392       ControllerInfo controller) throws AuthenticationException,
393       DriverSQLException
394   {
395     if (sequoiaUrl.isDebugEnabled())
396     {
397       System.out.println("connectToController: " + sequoiaUrl);
398       System.out.println("controller: " + controller);
399     }
400     HashMap JavaDoc urlParameters = sequoiaUrl.getParameters();
401     String JavaDoc user = (String JavaDoc) urlParameters.get(USER_PROPERTY);
402     if (user == null || user.equals(""))
403       throw new AuthenticationException("Invalid user name in connect");
404
405     // Check the password
406
String JavaDoc password = (String JavaDoc) urlParameters.get(PASSWORD_PROPERTY);
407     if (password == null)
408       password = "";
409
410     // Try to retrieve a reusable connection
411
if (!"false".equals(urlParameters.get(CONNECTION_POOLING_PROPERTY)))
412     { // Connection pooling is activated
413
java.sql.Connection JavaDoc c = retrievePendingClosingConnection(sequoiaUrl,
414           controller, user, password);
415       if (c != null)
416       {
417         if (sequoiaUrl.isDebugEnabled())
418           System.out.println("Reusing connection from pool");
419         return c; // Re-use this one
420
}
421     }
422
423     // Let's go for a new connection
424

425     // This is actually a connection constructor,
426
// we should try to move most of it below.
427
boolean sentVdbName = false;
428     boolean sentUserInfo = false;
429     try
430     {
431       // Connect to the controller
432
Socket JavaDoc socket = null;
433
434       // SSL enabled ?
435
if (SSL_ENABLED_PROPERTY
436           || "true".equals(urlParameters.get(SSL_PROPERTY)))
437       { // If the values have been defined in the URL, push them in the system
438
// properties
439
String JavaDoc keyStore = (String JavaDoc) urlParameters.get(SSL_KEY_STORE_PROPERTY);
440         if (keyStore != null)
441           System.setProperty("javax.net.ssl.keyStore", keyStore);
442
443         String JavaDoc keyStorePassword = (String JavaDoc) urlParameters
444             .get(SSL_KEY_STORE_PASSWORD_PROPERTY);
445         if (keyStorePassword != null)
446           System
447               .setProperty("javax.net.ssl.keyStorePassword", keyStorePassword);
448
449         String JavaDoc trustStore = (String JavaDoc) urlParameters
450             .get(SSL_TRUST_STORE_PROPERTY);
451         if (trustStore != null)
452           System.setProperty("javax.net.ssl.trustStore", trustStore);
453
454         String JavaDoc trustStorePassword = (String JavaDoc) urlParameters
455             .get(SSL_TRUST_STORE_PASSWORD_PROPERTY);
456         if (trustStorePassword != null)
457           System.setProperty("javax.net.ssl.trustStorePassword",
458               trustStorePassword);
459
460         SocketFactory sslFact = SocketFactoryFactory
461             .createFactory(SSLConfiguration.getDefaultConfig());
462         socket = sslFact.createSocket(controller.getHostname(), controller
463             .getPort());
464       }
465       else
466       {
467         // no ssl - we use ordinary socket
468
socket = new Socket JavaDoc(controller.getHostname(), controller.getPort());
469       }
470
471       // Disable Nagle algorithm else small messages are not sent
472
// (at least under Linux) even if we flush the output stream.
473
socket.setTcpNoDelay(true);
474
475       // SEQUOIA-506 fix: let's use the kernel TCP KeepAlive settings to detect
476
// dead controllers faster.
477
socket.setKeepAlive(true);
478
479       if (sequoiaUrl.isInfoEnabled())
480         System.out.println("Authenticating with controller " + controller);
481
482       DriverBufferedOutputStream out = new DriverBufferedOutputStream(socket,
483           sequoiaUrl.getDebugLevel());
484       // Send protocol version and database name
485
out.writeInt(Commands.ProtocolVersion);
486       out.writeLongUTF(sequoiaUrl.getDatabaseName());
487       out.flush();
488       sentVdbName = true;
489
490       // Send user information
491
out.writeLongUTF(user);
492       out.writeLongUTF(password);
493       out.flush();
494       sentUserInfo = true;
495
496       DriverBufferedInputStream in;
497       Connection con;
498
499       // Create input stream only here else it will block
500
in = new DriverBufferedInputStream(socket, sequoiaUrl.getDebugLevel());
501
502       con = createConnection(sequoiaUrl, controller, user, password, socket,
503           out, in);
504       return con;
505     } // try connect to the controller/connection constructor
506
catch (Exception JavaDoc re)
507     {
508       // FIXME SEQUOIA-576: if we have a minor problem like for instance,
509
// parsing the URL, we will... add the controller to the suspect list.
510
// Then we have an interesting race condition with the controller ping
511
// thread.
512
if (!sentVdbName)
513       {
514         if ((sequoiaUrl != null) && sequoiaUrl.isDebugEnabled())
515         {
516           System.out.println("Failed to connect to controller on "
517               + controller.getHostname() + ":" + controller.getPort() + " ("
518               + re + ")");
519           re.printStackTrace();
520         }
521         throw new DriverSQLException("Unable to connect to controller on "
522             + controller.getHostname() + ":" + controller.getPort() + " (" + re
523             + ")", re);
524       }
525       else if (re instanceof AuthenticationException)
526         throw (AuthenticationException) re;
527       else if (!sentUserInfo)
528         throw new DriverSQLException(
529             "Unable to connect to the virtual database (virtual database "
530                 + sequoiaUrl.getDatabaseName()
531                 + "is not available on controller" + controller.getHostname()
532                 + ":" + controller.getPort() + ")", re);
533       else
534         throw new DriverSQLException(
535             "Unable to connect to the virtual database ("
536                 + re.getLocalizedMessage() + ")", re);
537     }
538   }
539
540   /**
541    * Encapsulate the call to new Connection in to support sub-classing of the
542    * Connection object.
543    *
544    * @see Connection#Connection(Driver, Socket, DriverBufferedInputStream,
545    * DriverBufferedOutputStream, SequoiaUrl, ControllerInfo, String,
546    * String)
547    */

548   protected Connection createConnection(SequoiaUrl sequoiaUrl,
549       ControllerInfo controller, String JavaDoc user, String JavaDoc password, Socket JavaDoc socket,
550       DriverBufferedOutputStream out, DriverBufferedInputStream in)
551       throws AuthenticationException, IOException JavaDoc, SQLException JavaDoc
552   {
553     Connection con;
554     con = new Connection(this, socket, in, out, sequoiaUrl, controller, user,
555         password);
556     return con;
557   }
558
559   /**
560    * This extracts from the (too complex) client Properties a leaner and cleaner
561    * HashMap with is: - maybe empty but never null, - holding only the keys we
562    * are interested in, - its values are guaranteed to be strings, - no complex
563    * and hidden layered "defaults". See SEQUOIA-105 and SEQUOIA-440
564    *
565    * @param props to filter
566    * @return filtered properties
567    * @throws SQLException
568    */

569   protected Properties JavaDoc filterProperties(Properties JavaDoc props)
570   {
571     Properties JavaDoc filtered = new Properties JavaDoc();
572
573     if (props == null)
574       return filtered;
575
576     // extract only the keys we know
577
Iterator JavaDoc iter = driverPropertiesNames.iterator();
578     while (iter.hasNext())
579     {
580       String JavaDoc name = (String JavaDoc) iter.next();
581       String JavaDoc val = props.getProperty(name);
582       if (val == null)
583         continue;
584       filtered.setProperty(name, val);
585     }
586
587     return filtered;
588   }
589
590   /**
591    * This method is used to implement the transparent connection pooling and try
592    * to retrieve a connection that was recently closed to the given controller
593    * with the provided login/password information.
594    *
595    * @param url Sequoia URL object including parameters
596    * @param controllerInfo the controller to connect to
597    * @param user user name used for connection
598    * @param password password used for connection
599    * @return a connection that could be reuse or null if none
600    */

601   private java.sql.Connection JavaDoc retrievePendingClosingConnection(SequoiaUrl url,
602       ControllerInfo controllerInfo, String JavaDoc user, String JavaDoc password)
603   {
604     // Check if there is a connection that is about to be closed that could
605
// be reused. We take the bet that if a connection has been released by
606
// a client, in the general case, it will reuse the same connection.
607
// As we need to keep the work in the synchronized block as minimal as
608
// possible, we have to extract the string comparison
609
// (url,name,password,controller)from the sync block. This way, we cannot
610
// just read/compare/take the connection without synchronizing the whole
611
// thing. A solution is to systematically extract the first available
612
// connection in the sync block, and do the checkings outside the block. If
613
// we fail, we re-sync to put the connection back but in practice it is
614
// almost always a success and we don't really care to pay this extra cost
615
// once in a while.
616
try
617     {
618       Connection c;
619       synchronized (pendingConnectionClosing)
620       {
621         // Take the last one to prevent shifting all elements
622
c = (Connection) pendingConnectionClosing
623             .remove(pendingConnectionClosing.size() - 1);
624       }
625       if (url.equals(c.getSequoiaUrl()) // This compares all the Connection
626
// properties
627
&& controllerInfo.equals(c.getControllerInfo())
628           && user.equals(c.getUserName()) && password.equals(c.getPassword()))
629       { // Great! Take this one.
630
c.isClosed = false;
631         return c;
632       }
633       else
634       {
635         // Put this connection back, it is not good for us
636
synchronized (pendingConnectionClosing)
637         {
638           pendingConnectionClosing.add(c);
639           // Now scan the list for a suitable connection
640
for (Iterator JavaDoc iter = pendingConnectionClosing.iterator(); iter
641               .hasNext();)
642           {
643             Connection conn = (Connection) iter.next();
644             if (url.equals(conn.getSequoiaUrl()) // This compares all the
645
// Connection
646
// properties
647
&& controllerInfo.equals(conn.getControllerInfo())
648                 && user.equals(conn.getUserName())
649                 && password.equals(conn.getPassword()))
650             { // Great! Take this one.
651
iter.remove();
652               conn.isClosed = false;
653               return conn;
654             }
655           }
656         }
657       }
658     }
659     catch (IndexOutOfBoundsException JavaDoc ignore)
660     {
661       // No connection available
662
}
663     return null;
664   }
665
666   /**
667    * Tests if the URL is understood by the driver. Simply tries to construct a
668    * parsed URLs and catch the failure.
669    *
670    * @param url the JDBC URL.
671    * @return <code>true</code> if the URL is correct, otherwise an exception
672    * with extensive error message is thrown.
673    * @exception SQLException if the URL is incorrect an explicit error message
674    * is given.
675    */

676   public synchronized boolean acceptsURL(String JavaDoc url) throws SQLException JavaDoc
677   {
678     if (url == null)
679       return false;
680
681     try
682     {
683       SequoiaUrl sequoiaUrl = (SequoiaUrl) parsedUrlsCache.get(url);
684       if (sequoiaUrl == null) // Not in the cache
685
{
686         synchronized (this)
687         {
688           // Recheck here in case someone updated before we entered the
689
// synchronized block
690
sequoiaUrl = (SequoiaUrl) parsedUrlsCache.get(url);
691           if (sequoiaUrl == null)
692           {
693             // URL parsed here.
694
sequoiaUrl = new SequoiaUrl(this, url, new Properties JavaDoc());
695             // Update the cache anyway that can be useful later on
696
parsedUrlsCache.put(url, sequoiaUrl);
697           }
698         }
699       }
700       return true;
701     }
702     catch (SQLException JavaDoc e)
703     {
704       return false;
705     }
706   }
707
708   /**
709    * Change the database name in the provided URL.
710    *
711    * @param url URL to parse
712    * @param newDbName new database name to insert
713    * @return the updated URL
714    * @throws SQLException if an error occurs while parsing the url
715    */

716   public String JavaDoc changeDatabaseName(String JavaDoc url, String JavaDoc newDbName)
717       throws SQLException JavaDoc
718   {
719     StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
720     sb.append(sequoiaUrlHeader);
721
722     SequoiaUrl sequoiaUrl = (SequoiaUrl) parsedUrlsCache.get(url);
723     if (sequoiaUrl == null)
724     {
725       acceptsURL(url); // parse and put in cache
726
sequoiaUrl = (SequoiaUrl) parsedUrlsCache.get(url);
727     }
728
729     // append controller list
730
ControllerInfo[] controllerList = sequoiaUrl.getControllerList();
731     for (int i = 0; i < controllerList.length; i++)
732     {
733       if (i == 0)
734         sb.append(controllerList[i].toString());
735       else
736         sb.append("," + controllerList[i].toString());
737     }
738     sb.append("/" + newDbName);
739
740     // append parameters parsed above
741
HashMap JavaDoc params = sequoiaUrl.getParameters();
742     if (params != null)
743     {
744       Iterator JavaDoc paramsKeys = params.keySet().iterator();
745       String JavaDoc element = null;
746       while (paramsKeys.hasNext())
747       {
748         if (element == null)
749           sb.append("?");
750         else
751           sb.append("&");
752         element = (String JavaDoc) paramsKeys.next();
753         sb.append(element + "=" + params.get(paramsKeys));
754       }
755     }
756     return sb.toString();
757   }
758
759   /**
760    * Get the default transaction isolation level to use for this driver.
761    *
762    * @return java.sql.Connection.TRANSACTION_READ_UNCOMMITTED
763    */

764   protected int getDefaultTransactionIsolationLevel()
765   {
766     return java.sql.Connection.TRANSACTION_READ_UNCOMMITTED;
767   }
768
769   /**
770    * Returns the SequoiaJDBCRegExp value.
771    *
772    * @return Returns the SequoiaJDBCRegExp.
773    */

774   public JDBCRegExp getJDBCRegExp()
775   {
776     return jdbcRegExp;
777   }
778
779   /**
780    * This method is intended to allow a generic GUI tool to discover what
781    * properties it should prompt a human for in order to get enough information
782    * to connect to a database.
783    * <p>
784    * The only properties supported by Sequoia are:
785    * <ul>
786    * <li>HOST_PROPERTY</li>
787    * <li>PORT_PROPERTY</li>
788    * <li>DATABASE_PROPERTY</li>
789    * <li>USER_PROPERTY</li>
790    * <li>PASSWORD_PROPERTY</li>
791    * <li>ESCAPE_BACKSLASH_PROPERTY</li>
792    * <li>ESCAPE_CHARACTER_PROPERTY</li>
793    * <li>ESCAPE_SINGLE_QUOTE</li>
794    * <li>BOOLEAN_FALSE_PROPERTY</li>
795    * <li>BOOLEAN_TRUE_PROPERTY</li>
796    * <li>DRIVER_PROCESSED_PROPERTY</li>
797    * <li>CONNECTION_POOLING_PROPERTY</li>
798    * <li>PREFERRED_CONTROLLER_PROPERTY
799    * <li>
800    * </ul>
801    *
802    * @param url the URL of the database to connect to
803    * @param info a proposed list of tag/value pairs that will be sent on connect
804    * open.
805    * @return an array of <code>DriverPropertyInfo</code> objects describing
806    * possible properties. This array may be an empty array if no
807    * properties are required (note that this override any setting that
808    * might be set in the URL).
809    * @exception SQLException if the url is not valid
810    * @see java.sql.Driver#getPropertyInfo
811    */

812   public DriverPropertyInfo JavaDoc[] getPropertyInfo(String JavaDoc url, Properties JavaDoc info)
813       throws SQLException JavaDoc
814   {
815     if (!acceptsURL(url))
816       throw new SQLException JavaDoc("Invalid url " + url);
817
818     SequoiaUrl sequoiaUrl;
819     synchronized (this)
820     {
821       sequoiaUrl = (SequoiaUrl) parsedUrlsCache.get(url);
822       if (sequoiaUrl == null)
823         throw new SQLException JavaDoc("Error while retrieving URL information");
824     }
825     HashMap JavaDoc params = sequoiaUrl.getParameters();
826
827     String JavaDoc host = info.getProperty(HOST_PROPERTY);
828     if (host == null)
829     {
830       ControllerInfo[] controllerList = sequoiaUrl.getControllerList();
831       for (int i = 0; i < controllerList.length; i++)
832       {
833         ControllerInfo controller = controllerList[i];
834         if (i == 0)
835           host = controller.toString();
836         else
837           host += "," + controller.toString();
838       }
839     }
840     DriverPropertyInfo JavaDoc hostProp = new DriverPropertyInfo JavaDoc(HOST_PROPERTY, host);
841     hostProp.required = true;
842     hostProp.description = HOST_PROPERTY_DESCRIPTION;
843
844     DriverPropertyInfo JavaDoc portProp = new DriverPropertyInfo JavaDoc(PORT_PROPERTY, info
845         .getProperty(PORT_PROPERTY, Integer
846             .toString(SequoiaUrl.DEFAULT_CONTROLLER_PORT)));
847     portProp.required = false;
848     portProp.description = PORT_PROPERTY_DESCRIPTION;
849
850     String JavaDoc database = info.getProperty(DATABASE_PROPERTY);
851     if (database == null)
852       database = sequoiaUrl.getDatabaseName();
853     DriverPropertyInfo JavaDoc databaseProp = new DriverPropertyInfo JavaDoc(DATABASE_PROPERTY,
854         database);
855     databaseProp.required = true;
856     databaseProp.description = DATABASE_PROPERTY_DESCRIPTION;
857
858     String JavaDoc user = info.getProperty(USER_PROPERTY);
859     if (user == null)
860       user = (String JavaDoc) params.get(USER_PROPERTY);
861     DriverPropertyInfo JavaDoc userProp = new DriverPropertyInfo JavaDoc(USER_PROPERTY, user);
862     userProp.required = true;
863     userProp.description = USER_PROPERTY_DESCRIPTION;
864
865     String JavaDoc password = info.getProperty(PASSWORD_PROPERTY);
866     if (password == null)
867       password = (String JavaDoc) params.get(PASSWORD_PROPERTY);
868     DriverPropertyInfo JavaDoc passwordProp = new DriverPropertyInfo JavaDoc(PASSWORD_PROPERTY,
869         password);
870     passwordProp.required = true;
871     passwordProp.description = PASSWORD_PROPERTY_DESCRIPTION;
872
873     String JavaDoc ssl = info.getProperty(SSL_PROPERTY);
874     if (ssl == null)
875       ssl = (String JavaDoc) params.get(SSL_PROPERTY);
876     DriverPropertyInfo JavaDoc sslProp = new DriverPropertyInfo JavaDoc(SSL_PROPERTY, ssl);
877     sslProp.required = false;
878     sslProp.description = SSL_PROPERTY_DESCRIPTION;
879
880     String JavaDoc sslKeyStore = info.getProperty(SSL_KEY_STORE_PROPERTY);
881     if (sslKeyStore == null)
882       sslKeyStore = (String JavaDoc) params.get(SSL_KEY_STORE_PROPERTY);
883     DriverPropertyInfo JavaDoc sslKeyStoreProp = new DriverPropertyInfo JavaDoc(
884         SSL_KEY_STORE_PROPERTY, sslKeyStore);
885     sslKeyStoreProp.required = false;
886     sslKeyStoreProp.description = SSL_KEY_STORE_PROPERTY_DESCRIPTION;
887
888     String JavaDoc sslKeyStorePassword = info
889         .getProperty(SSL_KEY_STORE_PASSWORD_PROPERTY);
890     if (sslKeyStorePassword == null)
891       sslKeyStorePassword = (String JavaDoc) params
892           .get(SSL_KEY_STORE_PASSWORD_PROPERTY);
893     DriverPropertyInfo JavaDoc sslKeyStorePasswordProp = new DriverPropertyInfo JavaDoc(
894         SSL_KEY_STORE_PASSWORD_PROPERTY, sslKeyStorePassword);
895     sslKeyStorePasswordProp.required = false;
896     sslKeyStorePasswordProp.description = SSL_KEY_STORE_PASSWORD_PROPERTY_DESCRIPTION;
897
898     String JavaDoc sslTrustStore = info.getProperty(SSL_TRUST_STORE_PROPERTY);
899     if (sslTrustStore == null)
900       sslTrustStore = (String JavaDoc) params.get(SSL_TRUST_STORE_PROPERTY);
901     DriverPropertyInfo JavaDoc sslTrustStoreProp = new DriverPropertyInfo JavaDoc(
902         SSL_TRUST_STORE_PROPERTY, sslTrustStore);
903     sslTrustStoreProp.required = false;
904     sslTrustStoreProp.description = SSL_TRUST_STORE_PROPERTY_DESCRIPTION;
905
906     String JavaDoc sslTrustStorePassword = info
907         .getProperty(SSL_TRUST_STORE_PASSWORD_PROPERTY);
908     if (sslTrustStorePassword == null)
909       sslTrustStorePassword = (String JavaDoc) params
910           .get(SSL_TRUST_STORE_PASSWORD_PROPERTY);
911     DriverPropertyInfo JavaDoc sslTrustStorePasswordProp = new DriverPropertyInfo JavaDoc(
912         SSL_TRUST_STORE_PASSWORD_PROPERTY, sslTrustStorePassword);
913     sslTrustStorePasswordProp.required = false;
914     sslTrustStorePasswordProp.description = SSL_TRUST_STORE_PASSWORD_PROPERTY_DESCRIPTION;
915
916     String JavaDoc escapeChar = info.getProperty(ESCAPE_CHARACTER_PROPERTY);
917     if (escapeChar == null)
918       escapeChar = (String JavaDoc) params.get(ESCAPE_CHARACTER_PROPERTY);
919     DriverPropertyInfo JavaDoc escapeCharProp = new DriverPropertyInfo JavaDoc(
920         ESCAPE_CHARACTER_PROPERTY, escapeChar);
921     escapeCharProp.required = false;
922     escapeCharProp.description = ESCAPE_CHARACTER_PROPERTY_DESCRIPTION;
923
924     String JavaDoc escapeBackslash = info.getProperty(ESCAPE_BACKSLASH_PROPERTY);
925     if (escapeBackslash == null)
926       escapeBackslash = (String JavaDoc) params.get(ESCAPE_BACKSLASH_PROPERTY);
927     DriverPropertyInfo JavaDoc escapeBackProp = new DriverPropertyInfo JavaDoc(
928         ESCAPE_BACKSLASH_PROPERTY, escapeBackslash);
929     escapeBackProp.required = false;
930     escapeBackProp.description = ESCAPE_BACKSLASH_PROPERTY_DESCRIPTION;
931
932     String JavaDoc escapeSingleQuote = info.getProperty(ESCAPE_SINGLE_QUOTE_PROPERTY);
933     if (escapeSingleQuote == null)
934       escapeSingleQuote = (String JavaDoc) params.get(ESCAPE_SINGLE_QUOTE_PROPERTY);
935     DriverPropertyInfo JavaDoc escapeSingleProp = new DriverPropertyInfo JavaDoc(
936         ESCAPE_SINGLE_QUOTE_PROPERTY, escapeSingleQuote);
937     escapeSingleProp.required = false;
938     escapeSingleProp.description = ESCAPE_SINGLE_QUOTE_PROPERTY_DESCRIPTION;
939
940     String JavaDoc connectionPooling = info.getProperty(CONNECTION_POOLING_PROPERTY);
941     if (connectionPooling == null)
942       connectionPooling = (String JavaDoc) params.get(CONNECTION_POOLING_PROPERTY);
943     DriverPropertyInfo JavaDoc connectionPoolingProp = new DriverPropertyInfo JavaDoc(
944         CONNECTION_POOLING_PROPERTY, connectionPooling);
945     connectionPoolingProp.required = false;
946     connectionPoolingProp.description = CONNECTION_POOLING_PROPERTY_DESCRIPTION;
947
948     String JavaDoc preferredController = info
949         .getProperty(PREFERRED_CONTROLLER_PROPERTY);
950     if (preferredController == null)
951       preferredController = (String JavaDoc) params.get(PREFERRED_CONTROLLER_PROPERTY);
952     DriverPropertyInfo JavaDoc preferredControllerProp = new DriverPropertyInfo JavaDoc(
953         PREFERRED_CONTROLLER_PROPERTY, preferredController);
954     preferredControllerProp.required = false;
955     preferredControllerProp.description = PREFERRED_CONTROLLER_PROPERTY_DESCRIPTION;
956
957     String JavaDoc persistentConnection = info
958         .getProperty(PERSISTENT_CONNECTION_PROPERTY);
959     if (persistentConnection == null)
960       persistentConnection = (String JavaDoc) params
961           .get(PERSISTENT_CONNECTION_PROPERTY);
962     DriverPropertyInfo JavaDoc persistentConnectionProp = new DriverPropertyInfo JavaDoc(
963         PERSISTENT_CONNECTION_PROPERTY, persistentConnection);
964     persistentConnectionProp.required = false;
965     persistentConnectionProp.description = PERSISTENT_CONNECTION_PROPERTY_DESCRIPTION;
966
967     String JavaDoc retrieveSQLWarnings = info
968         .getProperty(RETRIEVE_SQL_WARNINGS_PROPERTY);
969     if (retrieveSQLWarnings == null)
970       retrieveSQLWarnings = (String JavaDoc) params.get(RETRIEVE_SQL_WARNINGS_PROPERTY);
971     DriverPropertyInfo JavaDoc retrieveSQLWarningsProp = new DriverPropertyInfo JavaDoc(
972         RETRIEVE_SQL_WARNINGS_PROPERTY, retrieveSQLWarnings);
973     retrieveSQLWarningsProp.required = false;
974     retrieveSQLWarningsProp.description = RETRIEVE_SQL_WARNINGS_PROPERTY_DESCRIPTION;
975
976     String JavaDoc getGeneratedKeys = info
977         .getProperty(ALWAYS_RETRIEVE_GENERATED_KEYS_PROPERTY);
978     if (getGeneratedKeys == null)
979       getGeneratedKeys = (String JavaDoc) params
980           .get(ALWAYS_RETRIEVE_GENERATED_KEYS_PROPERTY);
981     DriverPropertyInfo JavaDoc getGeneratedKeysProp = new DriverPropertyInfo JavaDoc(
982         ALWAYS_RETRIEVE_GENERATED_KEYS_PROPERTY, getGeneratedKeys);
983     getGeneratedKeysProp.required = false;
984     getGeneratedKeysProp.description = ALWAYS_RETRIEVE_GENERATED_KEYS_DESCRIPTION;
985
986     return new DriverPropertyInfo JavaDoc[]{hostProp, portProp, databaseProp, userProp,
987         passwordProp, escapeCharProp, escapeBackProp, escapeSingleProp,
988         connectionPoolingProp, preferredControllerProp,
989         persistentConnectionProp, retrieveSQLWarningsProp, getGeneratedKeysProp};
990   }
991
992   /**
993    * Gets the river's major version number
994    *
995    * @return the driver's major version number
996    */

997   public int getMajorVersion()
998   {
999     return MAJOR_VERSION;
1000  }
1001
1002  /**
1003   * Gets the driver's minor version number
1004   *
1005   * @return the driver's minor version number
1006   */

1007  public int getMinorVersion()
1008  {
1009    return MINOR_VERSION;
1010  }
1011
1012  /**
1013   * Reports whether the driver is a genuine JDBC compliant driver. A driver may
1014   * only report <code>true</code> here if it passes the JDBC compliance
1015   * tests, otherwise it is required to return <code>false</code>. JDBC
1016   * compliance requires full support for the JDBC API and full support for SQL
1017   * 92 Entry Level. We cannot ensure that the underlying JDBC drivers will be
1018   * JDBC compliant, so it is safer to return <code>false</code>.
1019   *
1020   * @return always <code>false</code>
1021   */

1022  public boolean jdbcCompliant()
1023  {
1024    return false;
1025  }
1026
1027  /**
1028   * @return True, escape processing of backslash is ON by default
1029   */

1030  public boolean getEscapeBackslash()
1031  {
1032    return true;
1033  }
1034
1035  /**
1036   * @return the default escape character
1037   */

1038  public String JavaDoc getEscapeChar()
1039  {
1040    return "\'";
1041  }
1042
1043  /**
1044   * @return True, escape processing of single quote is ON by default
1045   */

1046  public boolean getEscapeSingleQuote()
1047  {
1048    return true;
1049  }
1050
1051  /**
1052   * @return True, as connection pooling is activated by default
1053   */

1054  public boolean getConnectionPooling()
1055  {
1056    return true;
1057  }
1058
1059  /**
1060   * @return False, as connection are not persistent by default.
1061   */

1062  public boolean getPersistentConnection()
1063  {
1064    return false;
1065  }
1066
1067  /**
1068   * @return False, as retrieval of SQL warnings is disabled by default.
1069   */

1070  public boolean getRetrieveSQLWarnings()
1071  {
1072    return false;
1073  }
1074  
1075  /**
1076   * @return False, as retrieval of generated keys is not forced by default.
1077   */

1078  public boolean getRetrieveGeneratedKeys()
1079  {
1080    return false;
1081  }
1082}
Popular Tags