Save This Page
Home » MySQL-JDBC-5.1.11 » com.mysql.jdbc » [javadoc | source]
    1   /*
    2    Copyright  2002-2007 MySQL AB, 2008 Sun Microsystems
    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    There are special exceptions to the terms and conditions of the GPL
    9    as it is applied to this software. View the full text of the
   10    exception in file EXCEPTIONS-CONNECTOR-J in the directory of this
   11    software distribution.
   12   
   13    This program is distributed in the hope that it will be useful,
   14    but WITHOUT ANY WARRANTY; without even the implied warranty of
   15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16    GNU General Public License for more details.
   17   
   18    You should have received a copy of the GNU General Public License
   19    along with this program; if not, write to the Free Software
   20    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   21   
   22   
   23   
   24    */
   25   package com.mysql.jdbc;
   26   
   27   import java.io.IOException;
   28   import java.io.InputStream;
   29   import java.io.UnsupportedEncodingException;
   30   import java.net.URLDecoder;
   31   import java.sql.DriverPropertyInfo;
   32   import java.sql.SQLException;
   33   import java.util.ArrayList;
   34   import java.util.Iterator;
   35   import java.util.List;
   36   import java.util.Properties;
   37   import java.util.StringTokenizer;
   38   /**
   39    * The Java SQL framework allows for multiple database drivers. Each driver
   40    * should supply a class that implements the Driver interface
   41    * 
   42    * <p>
   43    * The DriverManager will try to load as many drivers as it can find and then
   44    * for any given connection request, it will ask each driver in turn to try to
   45    * connect to the target URL.
   46    * </p>
   47    * 
   48    * <p>
   49    * It is strongly recommended that each Driver class should be small and
   50    * standalone so that the Driver class can be loaded and queried without
   51    * bringing in vast quantities of supporting code.
   52    * </p>
   53    * 
   54    * <p>
   55    * When a Driver class is loaded, it should create an instance of itself and
   56    * register it with the DriverManager. This means that a user can load and
   57    * register a driver by doing Class.forName("foo.bah.Driver")
   58    * </p>
   59    * 
   60    * @author Mark Matthews
   61    * @version $Id: NonRegisteringDriver.java,v 1.1.2.1 2005/05/13 18:58:38
   62    *          mmatthews Exp $
   63    * 
   64    * @see org.gjt.mm.mysql.Connection
   65    * @see java.sql.Driver
   66    */
   67   public class NonRegisteringDriver implements java.sql.Driver {
   68   	private static final String REPLICATION_URL_PREFIX = "jdbc:mysql:replication://";
   69   
   70   	private static final String URL_PREFIX = "jdbc:mysql://";
   71   
   72   	private static final String MXJ_URL_PREFIX = "jdbc:mysql:mxj://";
   73   
   74   	private static final String LOADBALANCE_URL_PREFIX = "jdbc:mysql:loadbalance://";
   75   
   76   	/**
   77   	 * Key used to retreive the database value from the properties instance
   78   	 * passed to the driver.
   79   	 */
   80   	public static final String DBNAME_PROPERTY_KEY = "DBNAME";
   81   
   82   	/** Should the driver generate debugging output? */
   83   	public static final boolean DEBUG = false;
   84   
   85   	/** Index for hostname coming out of parseHostPortPair(). */
   86   	public final static int HOST_NAME_INDEX = 0;
   87   
   88   	/**
   89   	 * Key used to retreive the hostname value from the properties instance
   90   	 * passed to the driver.
   91   	 */
   92   	public static final String HOST_PROPERTY_KEY = "HOST";
   93   
   94   	public static final String NUM_HOSTS_PROPERTY_KEY = "NUM_HOSTS";
   95   	
   96   	/**
   97   	 * Key used to retreive the password value from the properties instance
   98   	 * passed to the driver.
   99   	 */
  100   	public static final String PASSWORD_PROPERTY_KEY = "password";
  101   
  102   	/** Index for port # coming out of parseHostPortPair(). */
  103   	public final static int PORT_NUMBER_INDEX = 1;
  104   
  105   	/**
  106   	 * Key used to retreive the port number value from the properties instance
  107   	 * passed to the driver.
  108   	 */
  109   	public static final String PORT_PROPERTY_KEY = "PORT";
  110   
  111   	public static final String PROPERTIES_TRANSFORM_KEY = "propertiesTransform";
  112   
  113   	/** Should the driver generate method-call traces? */
  114   	public static final boolean TRACE = false;
  115   
  116   	public static final String USE_CONFIG_PROPERTY_KEY = "useConfigs";
  117   
  118   	/**
  119   	 * Key used to retreive the username value from the properties instance
  120   	 * passed to the driver.
  121   	 */
  122   	public static final String USER_PROPERTY_KEY = "user";
  123   
  124   	/**
  125   	 * Gets the drivers major version number
  126   	 * 
  127   	 * @return the drivers major version number
  128   	 */
  129   	static int getMajorVersionInternal() {
  130   		return safeIntParse("@MYSQL_CJ_MAJOR_VERSION@"); //$NON-NLS-1$
  131   	}
  132   
  133   	/**
  134   	 * Get the drivers minor version number
  135   	 * 
  136   	 * @return the drivers minor version number
  137   	 */
  138   	static int getMinorVersionInternal() {
  139   		return safeIntParse("@MYSQL_CJ_MINOR_VERSION@"); //$NON-NLS-1$
  140   	}
  141   
  142   	/**
  143   	 * Parses hostPortPair in the form of [host][:port] into an array, with the
  144   	 * element of index HOST_NAME_INDEX being the host (or null if not
  145   	 * specified), and the element of index PORT_NUMBER_INDEX being the port (or
  146   	 * null if not specified).
  147   	 * 
  148   	 * @param hostPortPair
  149   	 *            host and port in form of of [host][:port]
  150   	 * 
  151   	 * @return array containing host and port as Strings
  152   	 * 
  153   	 * @throws SQLException
  154   	 *             if a parse error occurs
  155   	 */
  156   	protected static String[] parseHostPortPair(String hostPortPair)
  157   			throws SQLException {
  158   		int portIndex = hostPortPair.indexOf(":"); //$NON-NLS-1$
  159   
  160   		String[] splitValues = new String[2];
  161   
  162   		String hostname = null;
  163   
  164   		if (portIndex != -1) {
  165   			if ((portIndex + 1) < hostPortPair.length()) {
  166   				String portAsString = hostPortPair.substring(portIndex + 1);
  167   				hostname = hostPortPair.substring(0, portIndex);
  168   
  169   				splitValues[HOST_NAME_INDEX] = hostname;
  170   
  171   				splitValues[PORT_NUMBER_INDEX] = portAsString;
  172   			} else {
  173   				throw SQLError.createSQLException(Messages
  174   						.getString("NonRegisteringDriver.37"), //$NON-NLS-1$
  175   						SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE, null);
  176   			}
  177   		} else {
  178   			splitValues[HOST_NAME_INDEX] = hostPortPair;
  179   			splitValues[PORT_NUMBER_INDEX] = null;
  180   		}
  181   
  182   		return splitValues;
  183   	}
  184   
  185   	private static int safeIntParse(String intAsString) {
  186   		try {
  187   			return Integer.parseInt(intAsString);
  188   		} catch (NumberFormatException nfe) {
  189   			return 0;
  190   		}
  191   	}
  192   
  193   	/**
  194   	 * Construct a new driver and register it with DriverManager
  195   	 * 
  196   	 * @throws SQLException
  197   	 *             if a database error occurs.
  198   	 */
  199   	public NonRegisteringDriver() throws SQLException {
  200   		// Required for Class.forName().newInstance()
  201   	}
  202   
  203   	/**
  204   	 * Typically, drivers will return true if they understand the subprotocol
  205   	 * specified in the URL and false if they don't. This driver's protocols
  206   	 * start with jdbc:mysql:
  207   	 * 
  208   	 * @param url
  209   	 *            the URL of the driver
  210   	 * 
  211   	 * @return true if this driver accepts the given URL
  212   	 * 
  213   	 * @exception SQLException
  214   	 *                if a database-access error occurs
  215   	 * 
  216   	 * @see java.sql.Driver#acceptsURL
  217   	 */
  218   	public boolean acceptsURL(String url) throws SQLException {
  219   		return (parseURL(url, null) != null);
  220   	}
  221   
  222   	//
  223   	// return the database name property
  224   	//
  225   
  226   	/**
  227   	 * Try to make a database connection to the given URL. The driver should
  228   	 * return "null" if it realizes it is the wrong kind of driver to connect to
  229   	 * the given URL. This will be common, as when the JDBC driverManager is
  230   	 * asked to connect to a given URL, it passes the URL to each loaded driver
  231   	 * in turn.
  232   	 * 
  233   	 * <p>
  234   	 * The driver should raise an SQLException if it is the right driver to
  235   	 * connect to the given URL, but has trouble connecting to the database.
  236   	 * </p>
  237   	 * 
  238   	 * <p>
  239   	 * The java.util.Properties argument can be used to pass arbitrary string
  240   	 * tag/value pairs as connection arguments.
  241   	 * </p>
  242   	 * 
  243   	 * <p>
  244   	 * My protocol takes the form:
  245   	 * 
  246   	 * <PRE>
  247   	 * 
  248   	 * jdbc:mysql://host:port/database
  249   	 * 
  250   	 * </PRE>
  251   	 * 
  252   	 * </p>
  253   	 * 
  254   	 * @param url
  255   	 *            the URL of the database to connect to
  256   	 * @param info
  257   	 *            a list of arbitrary tag/value pairs as connection arguments
  258   	 * 
  259   	 * @return a connection to the URL or null if it isnt us
  260   	 * 
  261   	 * @exception SQLException
  262   	 *                if a database access error occurs
  263   	 * 
  264   	 * @see java.sql.Driver#connect
  265   	 */
  266   	public java.sql.Connection connect(String url, Properties info)
  267   			throws SQLException {
  268   		if (url != null) {
  269   			if (StringUtils.startsWithIgnoreCase(url, LOADBALANCE_URL_PREFIX)) {
  270   				return connectLoadBalanced(url, info);
  271   			} else if (StringUtils.startsWithIgnoreCase(url,
  272   					REPLICATION_URL_PREFIX)) {
  273   				return connectReplicationConnection(url, info);
  274   			}
  275   		}
  276   
  277   		Properties props = null;
  278   
  279   		if ((props = parseURL(url, info)) == null) {
  280   			return null;
  281   		}
  282   
  283   		try {
  284   			Connection newConn = com.mysql.jdbc.ConnectionImpl.getInstance(
  285   					host(props), port(props), props, database(props), url);
  286   
  287   			return newConn;
  288   		} catch (SQLException sqlEx) {
  289   			// Don't wrap SQLExceptions, throw
  290   			// them un-changed.
  291   			throw sqlEx;
  292   		} catch (Exception ex) {
  293   			SQLException sqlEx = SQLError.createSQLException(Messages
  294   					.getString("NonRegisteringDriver.17") //$NON-NLS-1$
  295   					+ ex.toString()
  296   					+ Messages.getString("NonRegisteringDriver.18"), //$NON-NLS-1$
  297   					SQLError.SQL_STATE_UNABLE_TO_CONNECT_TO_DATASOURCE, null);
  298   			
  299   			sqlEx.initCause(ex);
  300   			
  301   			throw sqlEx;
  302   		}
  303   	}
  304   
  305   	private java.sql.Connection connectLoadBalanced(String url, Properties info)
  306   			throws SQLException {
  307   		Properties parsedProps = parseURL(url, info);
  308   
  309   		// People tend to drop this in, it doesn't make sense
  310   		parsedProps.remove("roundRobinLoadBalance");
  311   		
  312   		if (parsedProps == null) {
  313   			return null;
  314   		}
  315   
  316   		int numHosts = Integer.parseInt(parsedProps.getProperty(NUM_HOSTS_PROPERTY_KEY));
  317   
  318   		List hostList = new ArrayList();
  319   
  320   		for (int i = 0; i < numHosts; i++) {
  321   			int index = i + 1;
  322   			
  323   			hostList.add(parsedProps.getProperty(HOST_PROPERTY_KEY + "." + index) + ":" 
  324   					+ parsedProps.getProperty(PORT_PROPERTY_KEY + "." + index));
  325   		}
  326   
  327   		LoadBalancingConnectionProxy proxyBal = new LoadBalancingConnectionProxy(
  328   				hostList, parsedProps);
  329   
  330   		return (java.sql.Connection) java.lang.reflect.Proxy.newProxyInstance(this
  331   				.getClass().getClassLoader(),
  332   				new Class[] { com.mysql.jdbc.Connection.class }, proxyBal);
  333   	}
  334   
  335   	protected java.sql.Connection connectReplicationConnection(String url, Properties info)
  336   			throws SQLException {
  337   		Properties parsedProps = parseURL(url, info);
  338   
  339   		if (parsedProps == null) {
  340   			return null;
  341   		}
  342   
  343   		Properties masterProps = (Properties) parsedProps.clone();
  344   		Properties slavesProps = (Properties) parsedProps.clone();
  345   
  346   		// Marker used for further testing later on, also when
  347   		// debugging
  348   		slavesProps.setProperty("com.mysql.jdbc.ReplicationConnection.isSlave",
  349   				"true");
  350   		
  351   		int numHosts = Integer.parseInt(parsedProps.getProperty(NUM_HOSTS_PROPERTY_KEY));
  352   
  353   		if (numHosts < 2) {
  354   			throw SQLError
  355   					.createSQLException(
  356   							"Must specify at least one slave host to connect to for master/slave replication load-balancing functionality",
  357   							SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE, null);
  358   		}
  359   		
  360   		for (int i = 1; i < numHosts; i++) {
  361   			int index = i + 1;
  362   			
  363   			masterProps.remove(HOST_PROPERTY_KEY + "." + index);
  364   			masterProps.remove(PORT_PROPERTY_KEY + "." + index);
  365   			
  366   			slavesProps.setProperty(HOST_PROPERTY_KEY + "." + i, parsedProps.getProperty(HOST_PROPERTY_KEY + "." + index));
  367   			slavesProps.setProperty(PORT_PROPERTY_KEY + "." + i, parsedProps.getProperty(PORT_PROPERTY_KEY + "." + index));
  368   		}
  369   
  370   		masterProps.setProperty(NUM_HOSTS_PROPERTY_KEY, "1");
  371   		slavesProps.remove(HOST_PROPERTY_KEY + "." + numHosts);
  372   		slavesProps.remove(PORT_PROPERTY_KEY + "." + numHosts);
  373   		slavesProps.setProperty(NUM_HOSTS_PROPERTY_KEY, String.valueOf(numHosts - 1));
  374   		slavesProps.setProperty(HOST_PROPERTY_KEY, slavesProps.getProperty(HOST_PROPERTY_KEY + ".1"));
  375   		slavesProps.setProperty(PORT_PROPERTY_KEY, slavesProps.getProperty(PORT_PROPERTY_KEY + ".1"));
  376   
  377   		return new ReplicationConnection(masterProps, slavesProps);
  378   	}
  379   
  380   	/**
  381   	 * Returns the database property from <code>props</code>
  382   	 * 
  383   	 * @param props
  384   	 *            the Properties to look for the database property.
  385   	 * 
  386   	 * @return the database name.
  387   	 */
  388   	public String database(Properties props) {
  389   		return props.getProperty(DBNAME_PROPERTY_KEY); //$NON-NLS-1$
  390   	}
  391   
  392   	/**
  393   	 * Gets the drivers major version number
  394   	 * 
  395   	 * @return the drivers major version number
  396   	 */
  397   	public int getMajorVersion() {
  398   		return getMajorVersionInternal();
  399   	}
  400   
  401   	/**
  402   	 * Get the drivers minor version number
  403   	 * 
  404   	 * @return the drivers minor version number
  405   	 */
  406   	public int getMinorVersion() {
  407   		return getMinorVersionInternal();
  408   	}
  409   
  410   	/**
  411   	 * The getPropertyInfo method is intended to allow a generic GUI tool to
  412   	 * discover what properties it should prompt a human for in order to get
  413   	 * enough information to connect to a database.
  414   	 * 
  415   	 * <p>
  416   	 * Note that depending on the values the human has supplied so far,
  417   	 * additional values may become necessary, so it may be necessary to iterate
  418   	 * through several calls to getPropertyInfo
  419   	 * </p>
  420   	 * 
  421   	 * @param url
  422   	 *            the Url of the database to connect to
  423   	 * @param info
  424   	 *            a proposed list of tag/value pairs that will be sent on
  425   	 *            connect open.
  426   	 * 
  427   	 * @return An array of DriverPropertyInfo objects describing possible
  428   	 *         properties. This array may be an empty array if no properties are
  429   	 *         required
  430   	 * 
  431   	 * @exception SQLException
  432   	 *                if a database-access error occurs
  433   	 * 
  434   	 * @see java.sql.Driver#getPropertyInfo
  435   	 */
  436   	public DriverPropertyInfo[] getPropertyInfo(String url, Properties info)
  437   			throws SQLException {
  438   		if (info == null) {
  439   			info = new Properties();
  440   		}
  441   
  442   		if ((url != null) && url.startsWith(URL_PREFIX)) { //$NON-NLS-1$
  443   			info = parseURL(url, info);
  444   		}
  445   
  446   		DriverPropertyInfo hostProp = new DriverPropertyInfo(HOST_PROPERTY_KEY, //$NON-NLS-1$
  447   				info.getProperty(HOST_PROPERTY_KEY)); //$NON-NLS-1$
  448   		hostProp.required = true;
  449   		hostProp.description = Messages.getString("NonRegisteringDriver.3"); //$NON-NLS-1$
  450   
  451   		DriverPropertyInfo portProp = new DriverPropertyInfo(PORT_PROPERTY_KEY, //$NON-NLS-1$
  452   				info.getProperty(PORT_PROPERTY_KEY, "3306")); //$NON-NLS-1$ //$NON-NLS-2$
  453   		portProp.required = false;
  454   		portProp.description = Messages.getString("NonRegisteringDriver.7"); //$NON-NLS-1$
  455   
  456   		DriverPropertyInfo dbProp = new DriverPropertyInfo(DBNAME_PROPERTY_KEY, //$NON-NLS-1$
  457   				info.getProperty(DBNAME_PROPERTY_KEY)); //$NON-NLS-1$
  458   		dbProp.required = false;
  459   		dbProp.description = "Database name"; //$NON-NLS-1$
  460   
  461   		DriverPropertyInfo userProp = new DriverPropertyInfo(USER_PROPERTY_KEY, //$NON-NLS-1$
  462   				info.getProperty(USER_PROPERTY_KEY)); //$NON-NLS-1$
  463   		userProp.required = true;
  464   		userProp.description = Messages.getString("NonRegisteringDriver.13"); //$NON-NLS-1$
  465   
  466   		DriverPropertyInfo passwordProp = new DriverPropertyInfo(
  467   				PASSWORD_PROPERTY_KEY, //$NON-NLS-1$
  468   				info.getProperty(PASSWORD_PROPERTY_KEY)); //$NON-NLS-1$
  469   		passwordProp.required = true;
  470   		passwordProp.description = Messages
  471   				.getString("NonRegisteringDriver.16"); //$NON-NLS-1$
  472   
  473   		DriverPropertyInfo[] dpi = ConnectionPropertiesImpl
  474   				.exposeAsDriverPropertyInfo(info, 5);
  475   
  476   		dpi[0] = hostProp;
  477   		dpi[1] = portProp;
  478   		dpi[2] = dbProp;
  479   		dpi[3] = userProp;
  480   		dpi[4] = passwordProp;
  481   
  482   		return dpi;
  483   	}
  484   
  485   	//
  486   	// return the value of any property this driver knows about
  487   	//
  488   
  489   	/**
  490   	 * Returns the hostname property
  491   	 * 
  492   	 * @param props
  493   	 *            the java.util.Properties instance to retrieve the hostname
  494   	 *            from.
  495   	 * 
  496   	 * @return the hostname
  497   	 */
  498   	public String host(Properties props) {
  499   		return props.getProperty(HOST_PROPERTY_KEY, "localhost"); //$NON-NLS-1$ //$NON-NLS-2$
  500   	}
  501   
  502   	/**
  503   	 * Report whether the driver is a genuine JDBC compliant driver. A driver
  504   	 * may only report "true" here if it passes the JDBC compliance tests,
  505   	 * otherwise it is required to return false. JDBC compliance requires full
  506   	 * support for the JDBC API and full support for SQL 92 Entry Level.
  507   	 * 
  508   	 * <p>
  509   	 * MySQL is not SQL92 compliant
  510   	 * </p>
  511   	 * 
  512   	 * @return is this driver JDBC compliant?
  513   	 */
  514   	public boolean jdbcCompliant() {
  515   		return false;
  516   	}
  517   
  518   	public Properties parseURL(String url, Properties defaults)
  519   			throws java.sql.SQLException {
  520   		Properties urlProps = (defaults != null) ? new Properties(defaults)
  521   				: new Properties();
  522   
  523   		if (url == null) {
  524   			return null;
  525   		}
  526   
  527   		if (!StringUtils.startsWithIgnoreCase(url, URL_PREFIX)
  528   				&& !StringUtils.startsWithIgnoreCase(url, MXJ_URL_PREFIX)
  529   				&& !StringUtils.startsWithIgnoreCase(url,
  530   						LOADBALANCE_URL_PREFIX)
  531   				&& !StringUtils.startsWithIgnoreCase(url,
  532   						REPLICATION_URL_PREFIX)) { //$NON-NLS-1$
  533   
  534   			return null;
  535   		}
  536   
  537   		int beginningOfSlashes = url.indexOf("//");
  538   
  539   		if (StringUtils.startsWithIgnoreCase(url, MXJ_URL_PREFIX)) {
  540   			
  541   			urlProps
  542   					.setProperty("socketFactory",
  543   							"com.mysql.management.driverlaunched.ServerLauncherSocketFactory");
  544   		}
  545   
  546   		/*
  547   		 * Parse parameters after the ? in the URL and remove them from the
  548   		 * original URL.
  549   		 */
  550   		int index = url.indexOf("?"); //$NON-NLS-1$
  551   
  552   		if (index != -1) {
  553   			String paramString = url.substring(index + 1, url.length());
  554   			url = url.substring(0, index);
  555   
  556   			StringTokenizer queryParams = new StringTokenizer(paramString, "&"); //$NON-NLS-1$
  557   
  558   			while (queryParams.hasMoreTokens()) {
  559   				String parameterValuePair = queryParams.nextToken();
  560   
  561   				int indexOfEquals = StringUtils.indexOfIgnoreCase(0,
  562   						parameterValuePair, "=");
  563   
  564   				String parameter = null;
  565   				String value = null;
  566   
  567   				if (indexOfEquals != -1) {
  568   					parameter = parameterValuePair.substring(0, indexOfEquals);
  569   
  570   					if (indexOfEquals + 1 < parameterValuePair.length()) {
  571   						value = parameterValuePair.substring(indexOfEquals + 1);
  572   					}
  573   				}
  574   
  575   				if ((value != null && value.length() > 0)
  576   						&& (parameter != null && parameter.length() > 0)) {
  577   					try {
  578   						urlProps.put(parameter, URLDecoder.decode(value,
  579   								"UTF-8"));
  580   					} catch (UnsupportedEncodingException badEncoding) {
  581   						// punt
  582   						urlProps.put(parameter, URLDecoder.decode(value));
  583   					} catch (NoSuchMethodError nsme) {
  584   						// punt again
  585   						urlProps.put(parameter, URLDecoder.decode(value));
  586   					}
  587   				}
  588   			}
  589   		}
  590   
  591   		url = url.substring(beginningOfSlashes + 2);
  592   
  593   		String hostStuff = null;
  594   
  595   		int slashIndex = url.indexOf("/"); //$NON-NLS-1$
  596   
  597   		if (slashIndex != -1) {
  598   			hostStuff = url.substring(0, slashIndex);
  599   
  600   			if ((slashIndex + 1) < url.length()) {
  601   				urlProps.put(DBNAME_PROPERTY_KEY, //$NON-NLS-1$
  602   						url.substring((slashIndex + 1), url.length()));
  603   			}
  604   		} else {
  605   			hostStuff = url;
  606   		}
  607   
  608   		int numHosts = 0;
  609   		
  610   		if ((hostStuff != null) && (hostStuff.trim().length() > 0)) {
  611   			StringTokenizer st = new StringTokenizer(hostStuff, ",");
  612   			
  613   			while (st.hasMoreTokens()) {
  614   				numHosts++;
  615   			
  616   				String[] hostPortPair = parseHostPortPair(st.nextToken());
  617   
  618   				if (hostPortPair[HOST_NAME_INDEX] != null && hostPortPair[HOST_NAME_INDEX].trim().length() > 0) {
  619   					urlProps.setProperty(HOST_PROPERTY_KEY + "." + numHosts, hostPortPair[HOST_NAME_INDEX]);
  620   				} else {
  621   					urlProps.setProperty(HOST_PROPERTY_KEY + "." + numHosts, "localhost");
  622   				}
  623   
  624   				if (hostPortPair[PORT_NUMBER_INDEX] != null) {
  625   					urlProps.setProperty(PORT_PROPERTY_KEY + "." + numHosts, hostPortPair[PORT_NUMBER_INDEX]);
  626   				} else {
  627   					urlProps.setProperty(PORT_PROPERTY_KEY + "." + numHosts, "3306");
  628   				}
  629   			}
  630   		} else {
  631   			numHosts = 1;
  632   			urlProps.setProperty(HOST_PROPERTY_KEY + ".1", "localhost");
  633   			urlProps.setProperty(PORT_PROPERTY_KEY + ".1", "3306");
  634   		}
  635   
  636   		urlProps.setProperty(NUM_HOSTS_PROPERTY_KEY, String.valueOf(numHosts));
  637   		urlProps.setProperty(HOST_PROPERTY_KEY, urlProps.getProperty(HOST_PROPERTY_KEY + ".1"));
  638   		urlProps.setProperty(PORT_PROPERTY_KEY, urlProps.getProperty(PORT_PROPERTY_KEY + ".1"));
  639   		
  640   		String propertiesTransformClassName = urlProps
  641   				.getProperty(PROPERTIES_TRANSFORM_KEY);
  642   
  643   		if (propertiesTransformClassName != null) {
  644   			try {
  645   				ConnectionPropertiesTransform propTransformer = (ConnectionPropertiesTransform) Class
  646   						.forName(propertiesTransformClassName).newInstance();
  647   
  648   				urlProps = propTransformer.transformProperties(urlProps);
  649   			} catch (InstantiationException e) {
  650   				throw SQLError.createSQLException(
  651   						"Unable to create properties transform instance '"
  652   								+ propertiesTransformClassName
  653   								+ "' due to underlying exception: "
  654   								+ e.toString(),
  655   						SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE, null);
  656   			} catch (IllegalAccessException e) {
  657   				throw SQLError.createSQLException(
  658   						"Unable to create properties transform instance '"
  659   								+ propertiesTransformClassName
  660   								+ "' due to underlying exception: "
  661   								+ e.toString(),
  662   						SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE, null);
  663   			} catch (ClassNotFoundException e) {
  664   				throw SQLError.createSQLException(
  665   						"Unable to create properties transform instance '"
  666   								+ propertiesTransformClassName
  667   								+ "' due to underlying exception: "
  668   								+ e.toString(),
  669   						SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE, null);
  670   			}
  671   		}
  672   
  673   		if (Util.isColdFusion() &&
  674   				urlProps.getProperty("autoConfigureForColdFusion", "true").equalsIgnoreCase("true")) {
  675   			String configs = urlProps.getProperty(USE_CONFIG_PROPERTY_KEY);
  676   			
  677   			StringBuffer newConfigs = new StringBuffer();
  678   			
  679   			if (configs != null) {
  680   				newConfigs.append(configs);
  681   				newConfigs.append(",");
  682   			}
  683   			
  684   			newConfigs.append("coldFusion");
  685   			
  686   			urlProps.setProperty(USE_CONFIG_PROPERTY_KEY, newConfigs.toString());
  687   		}
  688   		
  689   		// If we use a config, it actually should get overridden by anything in
  690   		// the URL or passed-in properties
  691   
  692   		String configNames = null;
  693   
  694   		if (defaults != null) {
  695   			configNames = defaults.getProperty(USE_CONFIG_PROPERTY_KEY);
  696   		}
  697   
  698   		if (configNames == null) {
  699   			configNames = urlProps.getProperty(USE_CONFIG_PROPERTY_KEY);
  700   		}
  701   
  702   		if (configNames != null) {
  703   			List splitNames = StringUtils.split(configNames, ",", true);
  704   
  705   			Properties configProps = new Properties();
  706   
  707   			Iterator namesIter = splitNames.iterator();
  708   
  709   			while (namesIter.hasNext()) {
  710   				String configName = (String) namesIter.next();
  711   
  712   				try {
  713   					InputStream configAsStream = getClass()
  714   							.getResourceAsStream(
  715   									"configs/" + configName + ".properties");
  716   
  717   					if (configAsStream == null) {
  718   						throw SQLError
  719   								.createSQLException(
  720   										"Can't find configuration template named '"
  721   												+ configName + "'",
  722   										SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE, null);
  723   					}
  724   					configProps.load(configAsStream);
  725   				} catch (IOException ioEx) {
  726   					SQLException sqlEx = SQLError.createSQLException(
  727   							"Unable to load configuration template '"
  728   									+ configName
  729   									+ "' due to underlying IOException: "
  730   									+ ioEx,
  731   							SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE, null);
  732   					sqlEx.initCause(ioEx);
  733   					
  734   					throw sqlEx;
  735   				}
  736   			}
  737   
  738   			Iterator propsIter = urlProps.keySet().iterator();
  739   
  740   			while (propsIter.hasNext()) {
  741   				String key = propsIter.next().toString();
  742   				String property = urlProps.getProperty(key);
  743   				configProps.setProperty(key, property);
  744   			}
  745   
  746   			urlProps = configProps;
  747   		}
  748   
  749   		// Properties passed in should override ones in URL
  750   
  751   		if (defaults != null) {
  752   			Iterator propsIter = defaults.keySet().iterator();
  753   
  754   			while (propsIter.hasNext()) {
  755   				String key = propsIter.next().toString();
  756   				if (!key.equals(NUM_HOSTS_PROPERTY_KEY)) {
  757   					String property = defaults.getProperty(key);
  758   					urlProps.setProperty(key, property);
  759   				}
  760   			}
  761   		}
  762   
  763   		return urlProps;
  764   	}
  765   
  766   	/**
  767   	 * Returns the port number property
  768   	 * 
  769   	 * @param props
  770   	 *            the properties to get the port number from
  771   	 * 
  772   	 * @return the port number
  773   	 */
  774   	public int port(Properties props) {
  775   		return Integer.parseInt(props.getProperty(PORT_PROPERTY_KEY, "3306")); //$NON-NLS-1$ //$NON-NLS-2$
  776   	}
  777   
  778   	/**
  779   	 * Returns the given property from <code>props</code>
  780   	 * 
  781   	 * @param name
  782   	 *            the property name
  783   	 * @param props
  784   	 *            the property instance to look in
  785   	 * 
  786   	 * @return the property value, or null if not found.
  787   	 */
  788   	public String property(String name, Properties props) {
  789   		return props.getProperty(name);
  790   	}
  791   }

Save This Page
Home » MySQL-JDBC-5.1.11 » com.mysql.jdbc » [javadoc | source]