Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/mysql/jdbc/NonRegisteringDriver.java


1   /*
2    Copyright (C) 2002-2004 MySQL AB
3   
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of version 2 of the GNU General Public License as
6    published by the Free Software Foundation.
7    
8   
9    There are special exceptions to the terms and conditions of the GPL 
10   as it is applied to this software. View the full text of the 
11   exception exception in file EXCEPTIONS-CONNECTOR-J in the directory of this 
12   software distribution.
13  
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18  
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  
23   */
24  package com.mysql.jdbc;
25  
26  import java.sql.DriverPropertyInfo;
27  import java.sql.SQLException;
28  
29  import java.util.Properties;
30  import java.util.StringTokenizer;
31  
32  
33  /**
34   * The Java SQL framework allows for multiple database drivers.  Each driver
35   * should supply a class that implements the Driver interface
36   * 
37   * <p>
38   * The DriverManager will try to load as many drivers as it can find and then
39   * for any given connection request, it will ask each driver in turn to try to
40   * connect to the target URL.
41   * </p>
42   * 
43   * <p>
44   * It is strongly recommended that each Driver class should be small and
45   * standalone so that the Driver class can be loaded and queried without
46   * bringing in vast quantities of supporting code.
47   * </p>
48   * 
49   * <p>
50   * When a Driver class is loaded, it should create an instance of itself and
51   * register it with the DriverManager.  This means that a user can load and
52   * register a driver by doing Class.forName("foo.bah.Driver")
53   * </p>
54   *
55   * @author Mark Matthews
56   * @version $Id: NonRegisteringDriver.java,v 1.1.2.20 2004/08/09 22:15:12 mmatthew Exp $
57   *
58   * @see org.gjt.mm.mysql.Connection
59   * @see java.sql.Driver
60   */
61  public class NonRegisteringDriver implements java.sql.Driver {
62      /** Should the driver generate debugging output? */
63      public static final boolean DEBUG = false;
64  
65      /** Should the driver generate method-call traces? */
66      public static final boolean TRACE = false;
67  
68      /** Index for hostname coming out of parseHostPortPair(). */
69      protected final static int HOST_NAME_INDEX = 0;
70  
71      /** Index for port # coming out of parseHostPortPair(). */
72      protected final static int PORT_NUMBER_INDEX = 1;
73  
74      /**
75       * Construct a new driver and register it with DriverManager
76       *
77       * @throws java.sql.SQLException if a database error occurs.
78       */
79      public NonRegisteringDriver() throws java.sql.SQLException {
80          // Required for Class.forName().newInstance()
81      }
82  
83      /**
84       * Gets the drivers major version number
85       *
86       * @return the drivers major version number
87       */
88      public int getMajorVersion() {
89          return getMajorVersionInternal();
90      }
91  
92      /**
93       * Get the drivers minor version number
94       *
95       * @return the drivers minor version number
96       */
97      public int getMinorVersion() {
98          return getMinorVersionInternal();
99      }
100 
101     /**
102      * The getPropertyInfo method is intended to allow a generic GUI tool to
103      * discover what properties it should prompt a human for in order to get
104      * enough information to connect to a database.
105      * 
106      * <p>
107      * Note that depending on the values the human has supplied so far,
108      * additional values may become necessary, so it may be necessary to
109      * iterate through several calls to getPropertyInfo
110      * </p>
111      *
112      * @param url the Url of the database to connect to
113      * @param info a proposed list of tag/value pairs that will be sent on
114      *        connect open.
115      *
116      * @return An array of DriverPropertyInfo objects describing possible
117      *         properties.  This array may be an empty array if no properties
118      *         are required
119      *
120      * @exception java.sql.SQLException if a database-access error occurs
121      *
122      * @see java.sql.Driver#getPropertyInfo
123      */
124     public DriverPropertyInfo[] getPropertyInfo(String url, Properties info)
125         throws java.sql.SQLException {
126         if (info == null) {
127             info = new Properties();
128         }
129 
130         if ((url != null) && url.startsWith("jdbc:mysql://")) {
131             info = parseURL(url, info);
132         }
133 
134         DriverPropertyInfo hostProp = new DriverPropertyInfo("HOST",
135                 info.getProperty("HOST"));
136         hostProp.required = true;
137         hostProp.description = "Hostname of MySQL Server";
138 
139         DriverPropertyInfo portProp = new DriverPropertyInfo("PORT",
140                 info.getProperty("PORT", "3306"));
141         portProp.required = false;
142         portProp.description = "Port number of MySQL Server";
143 
144         DriverPropertyInfo dbProp = new DriverPropertyInfo("DBNAME",
145                 info.getProperty("DBNAME"));
146         dbProp.required = false;
147         dbProp.description = "Database name";
148 
149         DriverPropertyInfo userProp = new DriverPropertyInfo("user",
150                 info.getProperty("user"));
151         userProp.required = true;
152         userProp.description = "Username to authenticate as";
153 
154         DriverPropertyInfo passwordProp = new DriverPropertyInfo("password",
155                 info.getProperty("password"));
156         passwordProp.required = true;
157         passwordProp.description = "Password to use for authentication";
158 
159         DriverPropertyInfo autoReconnect = new DriverPropertyInfo("autoReconnect",
160                 info.getProperty("autoReconnect", "false"));
161         autoReconnect.required = false;
162         autoReconnect.choices = new String[] { "true", "false" };
163         autoReconnect.description = "Should the driver try to re-establish bad connections?";
164 
165         DriverPropertyInfo maxReconnects = new DriverPropertyInfo("maxReconnects",
166                 info.getProperty("maxReconnects", "3"));
167         maxReconnects.required = false;
168         maxReconnects.description = "Maximum number of reconnects to attempt if autoReconnect is true";
169         ;
170 
171         DriverPropertyInfo initialTimeout = new DriverPropertyInfo("initialTimeout",
172                 info.getProperty("initialTimeout", "2"));
173         initialTimeout.required = false;
174         initialTimeout.description = "Initial timeout (seconds) to wait between failed connections";
175 
176         DriverPropertyInfo profileSql = new DriverPropertyInfo("profileSql",
177                 info.getProperty("profileSql", "false"));
178         profileSql.required = false;
179         profileSql.choices = new String[] { "true", "false" };
180         profileSql.description = "Trace queries and their execution/fetch times on STDERR (true/false) defaults to false";
181         ;
182 
183         DriverPropertyInfo socketTimeout = new DriverPropertyInfo("socketTimeout",
184                 info.getProperty("socketTimeout", "0"));
185         socketTimeout.required = false;
186         socketTimeout.description = "Timeout on network socket operations (0 means no timeout)";
187         ;
188 
189         DriverPropertyInfo useSSL = new DriverPropertyInfo("useSSL",
190                 info.getProperty("useSSL", "false"));
191         useSSL.required = false;
192         useSSL.choices = new String[] { "true", "false" };
193         useSSL.description = "Use SSL when communicating with the server?";
194         ;
195 
196         DriverPropertyInfo useCompression = new DriverPropertyInfo("useCompression",
197                 info.getProperty("useCompression", "false"));
198         useCompression.required = false;
199         useCompression.choices = new String[] { "true", "false" };
200         useCompression.description = "Use zlib compression when communicating with the server?";
201         ;
202 
203         DriverPropertyInfo paranoid = new DriverPropertyInfo("paranoid",
204                 info.getProperty("paranoid", "false"));
205         paranoid.required = false;
206         paranoid.choices = new String[] { "true", "false" };
207         paranoid.description = "Expose sensitive information in error messages and clear "
208             + "data structures holding sensitiven data when possible?";
209         ;
210 
211         DriverPropertyInfo useHostsInPrivileges = new DriverPropertyInfo("useHostsInPrivileges",
212                 info.getProperty("useHostsInPrivileges", "true"));
213         useHostsInPrivileges.required = false;
214         useHostsInPrivileges.choices = new String[] { "true", "false" };
215         useHostsInPrivileges.description = "Add '@hostname' to users in DatabaseMetaData.getColumn/TablePrivileges()";
216         ;
217 
218         DriverPropertyInfo interactiveClient = new DriverPropertyInfo("interactiveClient",
219                 info.getProperty("interactiveClient", "false"));
220         interactiveClient.required = false;
221         interactiveClient.choices = new String[] { "true", "false" };
222         interactiveClient.description = "Set the CLIENT_INTERACTIVE flag, which tells MySQL "
223             + "to timeout connections based on INTERACTIVE_TIMEOUT instead of WAIT_TIMEOUT";
224         ;
225 
226         DriverPropertyInfo useTimezone = new DriverPropertyInfo("useTimezone",
227                 info.getProperty("useTimezone", "false"));
228         useTimezone.required = false;
229         useTimezone.choices = new String[] { "true", "false" };
230         useTimezone.description = "Convert time/date types between client and server timezones";
231 
232         DriverPropertyInfo serverTimezone = new DriverPropertyInfo("serverTimezone",
233                 info.getProperty("serverTimezone", ""));
234         serverTimezone.required = false;
235         serverTimezone.description = "Override detection/mapping of timezone. Used when timezone from server doesn't map to Java timezone";
236 
237         DriverPropertyInfo connectTimeout = new DriverPropertyInfo("connectTimeout",
238                 info.getProperty("connectTimeout", "0"));
239         connectTimeout.required = false;
240         connectTimeout.description = "Timeout for socket connect (in milliseconds), with 0 being no timeout. Only works on JDK-1.4 or newer. Defaults to '0'.";
241 
242         DriverPropertyInfo queriesBeforeRetryMaster = new DriverPropertyInfo("queriesBeforeRetryMaster",
243                 info.getProperty("queriesBeforeRetryMaster", "50"));
244         queriesBeforeRetryMaster.required = false;
245         queriesBeforeRetryMaster.description = "Number of queries to issue before falling back to master when failed over "
246             + "(when using multi-host failover). Whichever condition is met first, "
247             + "'queriesBeforeRetryMaster' or 'secondsBeforeRetryMaster' will cause an "
248             + "attempt to be made to reconnect to the master. Defaults to 50.";
249         ;
250 
251         DriverPropertyInfo secondsBeforeRetryMaster = new DriverPropertyInfo("secondsBeforeRetryMaster",
252                 info.getProperty("secondsBeforeRetryMaster", "30"));
253         secondsBeforeRetryMaster.required = false;
254         secondsBeforeRetryMaster.description = "How long should the driver wait, when failed over, before attempting "
255             + "to reconnect to the master server? Whichever condition is met first, "
256             + "'queriesBeforeRetryMaster' or 'secondsBeforeRetryMaster' will cause an "
257             + "attempt to be made to reconnect to the master. Time in seconds, defaults to 30";
258 
259         DriverPropertyInfo useStreamLengthsInPrepStmts = new DriverPropertyInfo("useStreamLengthsInPrepStmts",
260                 info.getProperty("useStreamLengthsInPrepStmts", "true"));
261         useStreamLengthsInPrepStmts.required = false;
262         useStreamLengthsInPrepStmts.choices = new String[] { "true", "false" };
263         useStreamLengthsInPrepStmts.description = "Honor stream length parameter in "
264             + "PreparedStatement/ResultSet.setXXXStream() method calls (defaults to 'true')";
265 
266         DriverPropertyInfo continueBatchOnError = new DriverPropertyInfo("continueBatchOnError",
267                 info.getProperty("continueBatchOnError", "true"));
268         continueBatchOnError.required = false;
269         continueBatchOnError.choices = new String[] { "true", "false" };
270         continueBatchOnError.description = "Should the driver continue processing batch commands if "
271             + "one statement fails. The JDBC spec allows either way (defaults to 'true').";
272 
273         DriverPropertyInfo allowLoadLocalInfile = new DriverPropertyInfo("allowLoadLocalInfile",
274                 info.getProperty("allowLoadLocalInfile", "true"));
275         allowLoadLocalInfile.required = false;
276         allowLoadLocalInfile.choices = new String[] { "true", "false" };
277         allowLoadLocalInfile.description = "Should the driver allow use of 'LOAD DATA LOCAL INFILE...' (defaults to 'true').";
278 
279         DriverPropertyInfo strictUpdates = new DriverPropertyInfo("strictUpdates",
280                 info.getProperty("strictUpdates", "true"));
281         strictUpdates.required = false;
282         strictUpdates.choices = new String[] { "true", "false" };
283         strictUpdates.description = "Should the driver do strict checking (all primary keys selected) of updatable result sets?...' (defaults to 'true').";
284 
285         DriverPropertyInfo ignoreNonTxTables = new DriverPropertyInfo("ignoreNonTxTables",
286                 info.getProperty("ignoreNonTxTables", "false"));
287         ignoreNonTxTables.required = false;
288         ignoreNonTxTables.choices = new String[] { "true", "false" };
289         ignoreNonTxTables.description = "Ignore non-transactional table warning for rollback? (defaults to 'false').";
290 
291         DriverPropertyInfo clobberStreamingResults = new DriverPropertyInfo("clobberStreamingResults",
292                 info.getProperty("clobberStreamingResults", "false"));
293         clobberStreamingResults.required = false;
294         clobberStreamingResults.choices = new String[] { "true", "false" };
295         clobberStreamingResults.description = "This will cause a 'streaming' ResultSet to be automatically closed, "
296             + "and any oustanding data still streaming from the server to be discarded if another query is executed "
297             + "before all the data has been read from the server.";
298 
299         DriverPropertyInfo reconnectAtTxEnd = new DriverPropertyInfo("reconnectAtTxEnd",
300                 info.getProperty("reconnectAtTxEnd", "false"));
301         reconnectAtTxEnd.required = false;
302         reconnectAtTxEnd.choices = new String[] { "true", "false" };
303         reconnectAtTxEnd.description = "If autoReconnect is set to true, should the driver attempt reconnections"
304             + "at the end of every transaction? (true/false, defaults to false)";
305 
306         DriverPropertyInfo alwaysClearStream = new DriverPropertyInfo("alwaysClearStream",
307                 info.getProperty("alwaysClearStream", "false"));
308         alwaysClearStream.required = false;
309         alwaysClearStream.choices = new String[] { "true", "false" };
310         alwaysClearStream.description = "Should the driver clear any remaining data from the input stream before issuing"
311             + " a query? Normally not needed (approx 1-2%  perf. penalty, true/false, defaults to false)";
312 
313         DriverPropertyInfo cachePrepStmts = new DriverPropertyInfo("cachePrepStmts",
314                 info.getProperty("cachePrepStmts", "false"));
315         cachePrepStmts.required = false;
316         cachePrepStmts.choices = new String[] { "true", "false" };
317         cachePrepStmts.description = "Should the driver cache the parsing stage of PreparedStatements (true/false, default is 'false')";
318 
319         DriverPropertyInfo prepStmtCacheSize = new DriverPropertyInfo("prepStmtCacheSize",
320                 info.getProperty("prepStmtCacheSize", "25"));
321         prepStmtCacheSize.required = false;
322         prepStmtCacheSize.description = "If prepared statement caching is enabled, "
323             + "how many prepared statements should be cached? (default is '25')";
324 
325         DriverPropertyInfo prepStmtCacheSqlLimit = new DriverPropertyInfo("prepStmtCacheSqlLimit",
326                 info.getProperty("prepStmtCacheSqlLimit", "256"));
327         prepStmtCacheSqlLimit.required = false;
328         prepStmtCacheSqlLimit.description = "If prepared statement caching is enabled, "
329             + "what's the largest SQL the driver will cache the parsing for? (in chars, default is '256')";
330 
331         DriverPropertyInfo useUnbufferedInput = new DriverPropertyInfo("useUnbufferedInput",
332                 info.getProperty("useUnbufferedInput", "true"));
333         useUnbufferedInput.required = false;
334         useUnbufferedInput.description = "Don't use BufferedInputStream for reading data from the server true/false (default is 'true')";
335 
336         DriverPropertyInfo[] dpi = {
337             hostProp, portProp, dbProp, userProp, passwordProp, autoReconnect,
338             maxReconnects, initialTimeout, profileSql, socketTimeout, useSSL,
339             paranoid, useHostsInPrivileges, interactiveClient, useCompression,
340             useTimezone, serverTimezone, connectTimeout,
341             secondsBeforeRetryMaster, queriesBeforeRetryMaster,
342             useStreamLengthsInPrepStmts, continueBatchOnError,
343             allowLoadLocalInfile, strictUpdates, ignoreNonTxTables,
344             reconnectAtTxEnd, alwaysClearStream, cachePrepStmts,
345             prepStmtCacheSize, prepStmtCacheSqlLimit, useUnbufferedInput
346         };
347 
348         return dpi;
349     }
350 
351     /**
352      * Typically, drivers will return true if they understand the subprotocol
353      * specified in the URL and false if they don't.  This driver's protocols
354      * start with jdbc:mysql:
355      *
356      * @param url the URL of the driver
357      *
358      * @return true if this driver accepts the given URL
359      *
360      * @exception java.sql.SQLException if a database-access error occurs
361      *
362      * @see java.sql.Driver#acceptsURL
363      */
364     public boolean acceptsURL(String url) throws java.sql.SQLException {
365         return (parseURL(url, null) != null);
366     }
367 
368     /**
369      * Try to make a database connection to the given URL.  The driver should
370      * return "null" if it realizes it is the wrong kind of driver to connect
371      * to the given URL.  This will be common, as when the JDBC driverManager
372      * is asked to connect to a given URL, it passes the URL to each loaded
373      * driver in turn.
374      * 
375      * <p>
376      * The driver should raise an java.sql.SQLException if it is the right
377      * driver to connect to the given URL, but has trouble connecting to the
378      * database.
379      * </p>
380      * 
381      * <p>
382      * The java.util.Properties argument can be used to pass arbitrary string
383      * tag/value pairs as connection arguments.
384      * </p>
385      * 
386      * <p>
387      * My protocol takes the form:
388      * <PRE>
389      *    jdbc:mysql://host:port/database
390      * </PRE>
391      * </p>
392      *
393      * @param url the URL of the database to connect to
394      * @param info a list of arbitrary tag/value pairs as connection arguments
395      *
396      * @return a connection to the URL or null if it isnt us
397      *
398      * @exception java.sql.SQLException if a database access error occurs
399      * @throws SQLException DOCUMENT ME!
400      *
401      * @see java.sql.Driver#connect
402      */
403     public java.sql.Connection connect(String url, Properties info)
404         throws java.sql.SQLException {
405         Properties props = null;
406 
407         if ((props = parseURL(url, info)) == null) {
408             return null;
409         } else {
410             try {
411                 Connection newConn = new com.mysql.jdbc.Connection(host(props),
412                         port(props), props, database(props), url, this);
413 
414                 return (java.sql.Connection) newConn;
415             } catch (SQLException sqlEx) {
416                 // Don't wrap SQLExceptions, throw 
417                 // them un-changed.
418                 throw sqlEx;
419             } catch (Exception ex) {
420                 throw new SQLException(
421                     "Cannot load connection class because of underlying exception: '"
422                     + ex.toString() + "'.",
423                     SQLError.SQL_STATE_UNABLE_TO_CONNECT_TO_DATASOURCE);
424             }
425         }
426     }
427 
428     //
429     // return the database name property
430     //
431 
432     /**
433      * Returns the database property from <code>props</code>
434      *
435      * @param props the Properties to look for the database property.
436      *
437      * @return the database name.
438      */
439     public String database(Properties props) {
440         return props.getProperty("DBNAME");
441     }
442 
443     /**
444      * Returns the hostname property
445      *
446      * @param props the java.util.Properties instance to retrieve the hostname
447      *        from.
448      *
449      * @return the hostname
450      */
451     public String host(Properties props) {
452         return props.getProperty("HOST", "localhost");
453     }
454 
455     /**
456      * Report whether the driver is a genuine JDBC compliant driver.  A driver
457      * may only report "true" here if it passes the JDBC compliance tests,
458      * otherwise it is required to return false.  JDBC compliance requires
459      * full support for the JDBC API and full support for SQL 92 Entry Level.
460      * 
461      * <p>
462      * MySQL is not SQL92 compliant
463      * </p>
464      *
465      * @return is this driver JDBC compliant?
466      */
467     public boolean jdbcCompliant() {
468         return false;
469     }
470 
471     /**
472      * Constructs a new DriverURL, splitting the specified URL into its
473      * component parts
474      *
475      * @param url JDBC URL to parse
476      * @param defaults Default properties
477      *
478      * @return Properties with elements added from the url
479      *
480      * @exception java.sql.SQLException
481      */
482     public Properties parseURL(String url, Properties defaults)
483         throws java.sql.SQLException {
484         Properties urlProps = (defaults != null) ? defaults
485                                                  : new Properties(defaults);
486 
487         if (url == null) {
488             return null;
489         } else {
490             /*
491              * Parse parameters after the ? in the URL and remove
492              * them from the original URL.
493              */
494             int index = url.indexOf("?");
495 
496             if (index != -1) {
497                 String paramString = url.substring(index + 1, url.length());
498                 url = url.substring(0, index);
499 
500                 StringTokenizer queryParams = new StringTokenizer(paramString,
501                         "&");
502 
503                 while (queryParams.hasMoreTokens()) {
504                     StringTokenizer vp = new StringTokenizer(queryParams
505                             .nextToken(), "=");
506                     String param = "";
507 
508                     if (vp.hasMoreTokens()) {
509                         param = vp.nextToken();
510                     }
511 
512                     String value = "";
513 
514                     if (vp.hasMoreTokens()) {
515                         value = vp.nextToken();
516                     }
517 
518                     if ((value.length() > 0) && (param.length() > 0)) {
519                         urlProps.put(param, value);
520                     }
521                 }
522             }
523         }
524 
525         if (!StringUtils.startsWithIgnoreCase(url, "jdbc:mysql://")) {
526             return null;
527         }
528 
529         url = url.substring(13);
530 
531         String hostStuff = null;
532 
533         int slashIndex = url.indexOf("/");
534 
535         if (slashIndex != -1) {
536             hostStuff = url.substring(0, slashIndex);
537 
538             if ((slashIndex + 1) < url.length()) {
539                 urlProps.put("DBNAME",
540                     url.substring((slashIndex + 1), url.length()));
541             }
542         } else {
543             return null;
544         }
545 
546         if ((hostStuff != null) && (hostStuff.length() > 0)) {
547           urlProps.put("HOST", hostStuff);
548         }
549 
550         return urlProps;
551     }
552 
553     /**
554      * Returns the port number property
555      *
556      * @param props the properties to get the port number from
557      *
558      * @return the port number
559      */
560     public int port(Properties props) {
561         return Integer.parseInt(props.getProperty("PORT", "3306"));
562     }
563 
564     //
565     // return the value of any property this driver knows about
566     //
567 
568     /**
569      * Returns the given property from <code>props</code>
570      *
571      * @param name the property name
572      * @param props the property instance to look in
573      *
574      * @return the property value, or null if not found.
575      */
576     public String property(String name, Properties props) {
577         return props.getProperty(name);
578     }
579 
580     /**
581      * Parses hostPortPair in the form of [host][:port] into an array, with
582      * the element of index HOST_NAME_INDEX being the host (or null if not
583      * specified), and the element of index PORT_NUMBER_INDEX being the port
584      * (or null if not specified).
585      *
586      * @param hostPortPair host and port in form of of [host][:port]
587      *
588      * @return array containing host and port as Strings
589      *
590      * @throws SQLException if a parse error occurs
591      */
592     protected static String[] parseHostPortPair(String hostPortPair)
593         throws SQLException {
594         int portIndex = hostPortPair.indexOf(":");
595 
596         String[] splitValues = new String[2];
597 
598         String hostname = null;
599 
600         if (portIndex != -1) {
601             if ((portIndex + 1) < hostPortPair.length()) {
602                 String portAsString = hostPortPair.substring(portIndex + 1);
603                 hostname = hostPortPair.substring(0, portIndex);
604 
605                 splitValues[HOST_NAME_INDEX] = hostname;
606 
607                 splitValues[PORT_NUMBER_INDEX] = portAsString;
608             } else {
609                 throw new SQLException("Must specify port after ':' in connection string",
610                     SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE);
611             }
612         } else {
613             splitValues[HOST_NAME_INDEX] = hostPortPair;
614             splitValues[PORT_NUMBER_INDEX] = null;
615         }
616 
617         return splitValues;
618     }
619 
620     /**
621      * Gets the drivers major version number
622      *
623      * @return the drivers major version number
624      */
625     static int getMajorVersionInternal() {
626         return safeIntParse("3");
627     }
628 
629     /**
630      * Get the drivers minor version number
631      *
632      * @return the drivers minor version number
633      */
634     static int getMinorVersionInternal() {
635         return safeIntParse("0");
636     }
637 
638     private static int safeIntParse(String intAsString) {
639         try {
640             return Integer.parseInt(intAsString);
641         } catch (NumberFormatException nfe) {
642             return 0;
643         }
644     }
645 }