NonRegisteringDriver.java
上传用户:sxlinghang
上传日期:2022-07-20
资源大小:1405k
文件大小:28k
源码类别:

数据库编程

开发平台:

Java

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