EMMA Coverage Report (generated Tue Jul 25 14:15:05 CDT 2006)
[all classes][com.mysql.jdbc]

COVERAGE SUMMARY FOR SOURCE FILE [NonRegisteringDriver.java]

nameclass, %method, %block, %line, %
NonRegisteringDriver.java100% (1/1)69%  (11/16)76%  (491/649)78%  (113/145)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class NonRegisteringDriver100% (1/1)69%  (11/16)76%  (491/649)78%  (113/145)
acceptsURL (String): boolean 0%   (0/1)0%   (0/9)0%   (0/1)
getMajorVersion (): int 0%   (0/1)0%   (0/2)0%   (0/1)
getMinorVersion (): int 0%   (0/1)0%   (0/2)0%   (0/1)
jdbcCompliant (): boolean 0%   (0/1)0%   (0/2)0%   (0/1)
property (String, Properties): String 0%   (0/1)0%   (0/4)0%   (0/1)
safeIntParse (String): int 100% (1/1)50%  (3/6)33%  (1/3)
connect (String, Properties): Connection 100% (1/1)60%  (29/48)67%  (6/9)
parseURL (String, Properties): Properties 100% (1/1)74%  (282/381)78%  (64/82)
parseHostPortPair (String): String [] 100% (1/1)75%  (40/53)77%  (10/13)
getPropertyInfo (String, Properties): DriverPropertyInfo [] 100% (1/1)96%  (113/118)96%  (25/26)
NonRegisteringDriver (): void 100% (1/1)100% (3/3)100% (2/2)
database (Properties): String 100% (1/1)100% (4/4)100% (1/1)
getMajorVersionInternal (): int 100% (1/1)100% (3/3)100% (1/1)
getMinorVersionInternal (): int 100% (1/1)100% (3/3)100% (1/1)
host (Properties): String 100% (1/1)100% (5/5)100% (1/1)
port (Properties): int 100% (1/1)100% (6/6)100% (1/1)

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 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 */
25package com.mysql.jdbc;
26 
27import java.io.IOException;
28import java.io.InputStream;
29import java.io.UnsupportedEncodingException;
30import java.net.URLDecoder;
31import java.sql.DriverPropertyInfo;
32import java.sql.SQLException;
33 
34import java.util.Iterator;
35import java.util.List;
36import java.util.Properties;
37import java.util.StringTokenizer;
38 
39/**
40 * The Java SQL framework allows for multiple database drivers. Each driver
41 * should supply a class that implements the Driver interface
42 * 
43 * <p>
44 * The DriverManager will try to load as many drivers as it can find and then
45 * for any given connection request, it will ask each driver in turn to try to
46 * connect to the target URL.
47 * </p>
48 * 
49 * <p>
50 * It is strongly recommended that each Driver class should be small and
51 * standalone so that the Driver class can be loaded and queried without
52 * bringing in vast quantities of supporting code.
53 * </p>
54 * 
55 * <p>
56 * When a Driver class is loaded, it should create an instance of itself and
57 * register it with the DriverManager. This means that a user can load and
58 * register a driver by doing Class.forName("foo.bah.Driver")
59 * </p>
60 * 
61 * @author Mark Matthews
62 * @version $Id: NonRegisteringDriver.java,v 1.1.2.1 2005/05/13 18:58:38
63 *          mmatthews Exp $
64 * 
65 * @see org.gjt.mm.mysql.Connection
66 * @see java.sql.Driver
67 */
68public class NonRegisteringDriver implements java.sql.Driver {
69        /**
70         * Key used to retreive the database value from the properties instance
71         * passed to the driver.
72         */
73        public static final String DBNAME_PROPERTY_KEY = "DBNAME";
74 
75        /** Should the driver generate debugging output? */
76        public static final boolean DEBUG = false;
77 
78        /** Index for hostname coming out of parseHostPortPair(). */
79        public final static int HOST_NAME_INDEX = 0;
80 
81        /**
82         * Key used to retreive the hostname value from the properties instance
83         * passed to the driver.
84         */
85        public static final String HOST_PROPERTY_KEY = "HOST";
86 
87        /**
88         * Key used to retreive the password value from the properties instance
89         * passed to the driver.
90         */
91        public static final String PASSWORD_PROPERTY_KEY = "password";
92 
93        /** Index for port # coming out of parseHostPortPair(). */
94        public final static int PORT_NUMBER_INDEX = 1;
95 
96        /**
97         * Key used to retreive the port number value from the properties instance
98         * passed to the driver.
99         */
100        public static final String PORT_PROPERTY_KEY = "PORT";
101 
102        public static final String PROPERTIES_TRANSFORM_KEY = "propertiesTransform";
103 
104        /** Should the driver generate method-call traces? */
105        public static final boolean TRACE = false;
106 
107        public static final String USE_CONFIG_PROPERTY_KEY = "useConfigs";
108 
109        /**
110         * Key used to retreive the username value from the properties instance
111         * passed to the driver.
112         */
113        public static final String USER_PROPERTY_KEY = "user";
114 
115        /**
116         * Gets the drivers major version number
117         * 
118         * @return the drivers major version number
119         */
120        static int getMajorVersionInternal() {
121                return safeIntParse("5"); //$NON-NLS-1$
122        }
123 
124        /**
125         * Get the drivers minor version number
126         * 
127         * @return the drivers minor version number
128         */
129        static int getMinorVersionInternal() {
130                return safeIntParse("0"); //$NON-NLS-1$
131        }
132 
133        /**
134         * Parses hostPortPair in the form of [host][:port] into an array, with the
135         * element of index HOST_NAME_INDEX being the host (or null if not
136         * specified), and the element of index PORT_NUMBER_INDEX being the port (or
137         * null if not specified).
138         * 
139         * @param hostPortPair
140         *            host and port in form of of [host][:port]
141         * 
142         * @return array containing host and port as Strings
143         * 
144         * @throws SQLException
145         *             if a parse error occurs
146         */
147        protected static String[] parseHostPortPair(String hostPortPair)
148                        throws SQLException {
149                int portIndex = hostPortPair.indexOf(":"); //$NON-NLS-1$
150 
151                String[] splitValues = new String[2];
152 
153                String hostname = null;
154 
155                if (portIndex != -1) {
156                        if ((portIndex + 1) < hostPortPair.length()) {
157                                String portAsString = hostPortPair.substring(portIndex + 1);
158                                hostname = hostPortPair.substring(0, portIndex);
159 
160                                splitValues[HOST_NAME_INDEX] = hostname;
161 
162                                splitValues[PORT_NUMBER_INDEX] = portAsString;
163                        } else {
164                                throw SQLError.createSQLException(Messages
165                                                .getString("NonRegisteringDriver.37"), //$NON-NLS-1$
166                                                SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE);
167                        }
168                } else {
169                        splitValues[HOST_NAME_INDEX] = hostPortPair;
170                        splitValues[PORT_NUMBER_INDEX] = null;
171                }
172 
173                return splitValues;
174        }
175 
176        private static int safeIntParse(String intAsString) {
177                try {
178                        return Integer.parseInt(intAsString);
179                } catch (NumberFormatException nfe) {
180                        return 0;
181                }
182        }
183 
184        /**
185         * Construct a new driver and register it with DriverManager
186         * 
187         * @throws SQLException
188         *             if a database error occurs.
189         */
190        public NonRegisteringDriver() throws SQLException {
191                // Required for Class.forName().newInstance()
192        }
193 
194        /**
195         * Typically, drivers will return true if they understand the subprotocol
196         * specified in the URL and false if they don't. This driver's protocols
197         * start with jdbc:mysql:
198         * 
199         * @param url
200         *            the URL of the driver
201         * 
202         * @return true if this driver accepts the given URL
203         * 
204         * @exception SQLException
205         *                if a database-access error occurs
206         * 
207         * @see java.sql.Driver#acceptsURL
208         */
209        public boolean acceptsURL(String url) throws SQLException {
210                return (parseURL(url, null) != null);
211        }
212 
213        //
214        // return the database name property
215        //
216 
217        /**
218         * Try to make a database connection to the given URL. The driver should
219         * return "null" if it realizes it is the wrong kind of driver to connect to
220         * the given URL. This will be common, as when the JDBC driverManager is
221         * asked to connect to a given URL, it passes the URL to each loaded driver
222         * in turn.
223         * 
224         * <p>
225         * The driver should raise an SQLException if it is the right driver to
226         * connect to the given URL, but has trouble connecting to the database.
227         * </p>
228         * 
229         * <p>
230         * The java.util.Properties argument can be used to pass arbitrary string
231         * tag/value pairs as connection arguments.
232         * </p>
233         * 
234         * <p>
235         * My protocol takes the form:
236         * 
237         * <PRE>
238         * 
239         * jdbc:mysql://host:port/database
240         * 
241         * </PRE>
242         * 
243         * </p>
244         * 
245         * @param url
246         *            the URL of the database to connect to
247         * @param info
248         *            a list of arbitrary tag/value pairs as connection arguments
249         * 
250         * @return a connection to the URL or null if it isnt us
251         * 
252         * @exception SQLException
253         *                if a database access error occurs
254         * 
255         * @see java.sql.Driver#connect
256         */
257        public java.sql.Connection connect(String url, Properties info)
258                        throws SQLException {
259                Properties props = null;
260 
261                if ((props = parseURL(url, info)) == null) {
262                        return null;
263                }
264 
265                try {
266                        Connection newConn = new com.mysql.jdbc.Connection(host(props),
267                                        port(props), props, database(props), url);
268 
269                        return newConn;
270                } catch (SQLException sqlEx) {
271                        // Don't wrap SQLExceptions, throw
272                        // them un-changed.
273                        throw sqlEx;
274                } catch (Exception ex) {
275                        throw SQLError.createSQLException(Messages
276                                        .getString("NonRegisteringDriver.17") //$NON-NLS-1$
277                                        + ex.toString()
278                                        + Messages.getString("NonRegisteringDriver.18"), //$NON-NLS-1$
279                                        SQLError.SQL_STATE_UNABLE_TO_CONNECT_TO_DATASOURCE);
280                }
281        }
282 
283        /**
284         * Returns the database property from <code>props</code>
285         * 
286         * @param props
287         *            the Properties to look for the database property.
288         * 
289         * @return the database name.
290         */
291        public String database(Properties props) {
292                return props.getProperty(DBNAME_PROPERTY_KEY); //$NON-NLS-1$
293        }
294 
295        /**
296         * Gets the drivers major version number
297         * 
298         * @return the drivers major version number
299         */
300        public int getMajorVersion() {
301                return getMajorVersionInternal();
302        }
303 
304        /**
305         * Get the drivers minor version number
306         * 
307         * @return the drivers minor version number
308         */
309        public int getMinorVersion() {
310                return getMinorVersionInternal();
311        }
312 
313        /**
314         * The getPropertyInfo method is intended to allow a generic GUI tool to
315         * discover what properties it should prompt a human for in order to get
316         * enough information to connect to a database.
317         * 
318         * <p>
319         * Note that depending on the values the human has supplied so far,
320         * additional values may become necessary, so it may be necessary to iterate
321         * through several calls to getPropertyInfo
322         * </p>
323         * 
324         * @param url
325         *            the Url of the database to connect to
326         * @param info
327         *            a proposed list of tag/value pairs that will be sent on
328         *            connect open.
329         * 
330         * @return An array of DriverPropertyInfo objects describing possible
331         *         properties. This array may be an empty array if no properties are
332         *         required
333         * 
334         * @exception SQLException
335         *                if a database-access error occurs
336         * 
337         * @see java.sql.Driver#getPropertyInfo
338         */
339        public DriverPropertyInfo[] getPropertyInfo(String url, Properties info)
340                        throws SQLException {
341                if (info == null) {
342                        info = new Properties();
343                }
344 
345                if ((url != null) && url.startsWith("jdbc:mysql://")) { //$NON-NLS-1$
346                        info = parseURL(url, info);
347                }
348 
349                DriverPropertyInfo hostProp = new DriverPropertyInfo(HOST_PROPERTY_KEY, //$NON-NLS-1$
350                                info.getProperty(HOST_PROPERTY_KEY)); //$NON-NLS-1$
351                hostProp.required = true;
352                hostProp.description = Messages.getString("NonRegisteringDriver.3"); //$NON-NLS-1$
353 
354                DriverPropertyInfo portProp = new DriverPropertyInfo(PORT_PROPERTY_KEY, //$NON-NLS-1$
355                                info.getProperty(PORT_PROPERTY_KEY, "3306")); //$NON-NLS-1$ //$NON-NLS-2$
356                portProp.required = false;
357                portProp.description = Messages.getString("NonRegisteringDriver.7"); //$NON-NLS-1$
358 
359                DriverPropertyInfo dbProp = new DriverPropertyInfo(DBNAME_PROPERTY_KEY, //$NON-NLS-1$
360                                info.getProperty(DBNAME_PROPERTY_KEY)); //$NON-NLS-1$
361                dbProp.required = false;
362                dbProp.description = "Database name"; //$NON-NLS-1$
363 
364                DriverPropertyInfo userProp = new DriverPropertyInfo(USER_PROPERTY_KEY, //$NON-NLS-1$
365                                info.getProperty(USER_PROPERTY_KEY)); //$NON-NLS-1$
366                userProp.required = true;
367                userProp.description = Messages.getString("NonRegisteringDriver.13"); //$NON-NLS-1$
368 
369                DriverPropertyInfo passwordProp = new DriverPropertyInfo(
370                                PASSWORD_PROPERTY_KEY, //$NON-NLS-1$
371                                info.getProperty(PASSWORD_PROPERTY_KEY)); //$NON-NLS-1$
372                passwordProp.required = true;
373                passwordProp.description = Messages
374                                .getString("NonRegisteringDriver.16"); //$NON-NLS-1$
375 
376                DriverPropertyInfo[] dpi = ConnectionProperties
377                                .exposeAsDriverPropertyInfo(info, 5);
378 
379                dpi[0] = hostProp;
380                dpi[1] = portProp;
381                dpi[2] = dbProp;
382                dpi[3] = userProp;
383                dpi[4] = passwordProp;
384 
385                return dpi;
386        }
387 
388        //
389        // return the value of any property this driver knows about
390        //
391 
392        /**
393         * Returns the hostname property
394         * 
395         * @param props
396         *            the java.util.Properties instance to retrieve the hostname
397         *            from.
398         * 
399         * @return the hostname
400         */
401        public String host(Properties props) {
402                return props.getProperty(HOST_PROPERTY_KEY, "localhost"); //$NON-NLS-1$ //$NON-NLS-2$
403        }
404 
405        /**
406         * Report whether the driver is a genuine JDBC compliant driver. A driver
407         * may only report "true" here if it passes the JDBC compliance tests,
408         * otherwise it is required to return false. JDBC compliance requires full
409         * support for the JDBC API and full support for SQL 92 Entry Level.
410         * 
411         * <p>
412         * MySQL is not SQL92 compliant
413         * </p>
414         * 
415         * @return is this driver JDBC compliant?
416         */
417        public boolean jdbcCompliant() {
418                return false;
419        }
420 
421        /**
422         * 
423         * 
424         * @param url
425         *            ...
426         * @param defaults
427         *            ...
428         * 
429         * @return ...
430         * 
431         * @throws java.sql.SQLException
432         *             ...
433         */
434        public Properties parseURL(String url, Properties defaults)
435                        throws java.sql.SQLException {
436                Properties urlProps = (defaults != null) ? new Properties(defaults)
437                                : new Properties();
438 
439                if (url == null) {
440                        return null;
441                }
442 
443                if (!StringUtils.startsWithIgnoreCase(url, "jdbc:mysql://") && 
444                                !StringUtils.startsWithIgnoreCase(url, "jdbc:mysql:mxj://")) { //$NON-NLS-1$
445 
446                        return null;
447                }
448 
449                int beginningOfSlashes = 13;
450                
451                if (StringUtils.startsWithIgnoreCase(url, "jdbc:mysql:mxj://")) {
452                        beginningOfSlashes = 17;
453                        
454                        urlProps.setProperty("socketFactory", 
455                                "com.mysql.management.driverlaunched.ServerLauncherSocketFactory");
456                }
457                
458                /*
459                 * Parse parameters after the ? in the URL and remove them from the
460                 * original URL.
461                 */
462                int index = url.indexOf("?"); //$NON-NLS-1$
463 
464                if (index != -1) {
465                        String paramString = url.substring(index + 1, url.length());
466                        url = url.substring(0, index);
467 
468                        StringTokenizer queryParams = new StringTokenizer(paramString, "&"); //$NON-NLS-1$
469 
470                        while (queryParams.hasMoreTokens()) {
471                                String parameterValuePair = queryParams.nextToken();
472 
473                                int indexOfEquals = StringUtils.indexOfIgnoreCase(0,
474                                                parameterValuePair, "=");
475 
476                                String parameter = null;
477                                String value = null;
478 
479                                if (indexOfEquals != -1) {
480                                        parameter = parameterValuePair.substring(0, indexOfEquals);
481 
482                                        if (indexOfEquals + 1 < parameterValuePair.length()) {
483                                                value = parameterValuePair.substring(indexOfEquals + 1);
484                                        }
485                                }
486 
487                                if ((value != null && value.length() > 0)
488                                                && (parameter != null && parameter.length() > 0)) {
489                                        try {
490                                                urlProps.put(parameter, URLDecoder.decode(value,
491                                                                "UTF-8"));
492                                        } catch (UnsupportedEncodingException badEncoding) {
493                                                // punt
494                                                urlProps.put(parameter, URLDecoder.decode(value));
495                                        } catch (NoSuchMethodError nsme) {
496                                                // punt again
497                                                urlProps.put(parameter,  URLDecoder.decode(value));
498                                        }
499                                }
500                        }
501                }
502 
503                url = url.substring(beginningOfSlashes);
504 
505                String hostStuff = null;
506 
507                int slashIndex = url.indexOf("/"); //$NON-NLS-1$
508 
509                if (slashIndex != -1) {
510                        hostStuff = url.substring(0, slashIndex);
511 
512                        if ((slashIndex + 1) < url.length()) {
513                                urlProps.put(DBNAME_PROPERTY_KEY, //$NON-NLS-1$
514                                                url.substring((slashIndex + 1), url.length()));
515                        }
516                } else {
517                        return null;
518                }
519 
520                if ((hostStuff != null) && (hostStuff.length() > 0)) {
521                        urlProps.put(HOST_PROPERTY_KEY, hostStuff); //$NON-NLS-1$
522                }
523 
524                String propertiesTransformClassName = urlProps
525                                .getProperty(PROPERTIES_TRANSFORM_KEY);
526 
527                if (propertiesTransformClassName != null) {
528                        try {
529                                ConnectionPropertiesTransform propTransformer = (ConnectionPropertiesTransform) Class
530                                                .forName(propertiesTransformClassName).newInstance();
531 
532                                urlProps = propTransformer.transformProperties(urlProps);
533                        } catch (InstantiationException e) {
534                                throw SQLError.createSQLException(
535                                                "Unable to create properties transform instance '"
536                                                                + propertiesTransformClassName
537                                                                + "' due to underlying exception: "
538                                                                + e.toString(),
539                                                SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE);
540                        } catch (IllegalAccessException e) {
541                                throw SQLError.createSQLException(
542                                                "Unable to create properties transform instance '"
543                                                                + propertiesTransformClassName
544                                                                + "' due to underlying exception: "
545                                                                + e.toString(),
546                                                SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE);
547                        } catch (ClassNotFoundException e) {
548                                throw SQLError.createSQLException(
549                                                "Unable to create properties transform instance '"
550                                                                + propertiesTransformClassName
551                                                                + "' due to underlying exception: "
552                                                                + e.toString(),
553                                                SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE);
554                        }
555                }
556 
557                // If we use a config, it actually should get overridden by anything in
558                // the URL or passed-in properties
559 
560                String configNames = null;
561 
562                if (defaults != null) {
563                        configNames = defaults.getProperty(USE_CONFIG_PROPERTY_KEY);
564                }
565 
566                if (configNames == null) {
567                        configNames = urlProps.getProperty(USE_CONFIG_PROPERTY_KEY);
568                }
569 
570                if (configNames != null) {
571                        List splitNames = StringUtils.split(configNames, ",", true);
572 
573                        Properties configProps = new Properties();
574 
575                        Iterator namesIter = splitNames.iterator();
576 
577                        while (namesIter.hasNext()) {
578                                String configName = (String) namesIter.next();
579 
580                                try {
581                                        InputStream configAsStream = getClass()
582                                                        .getResourceAsStream(
583                                                                        "configs/" + configName + ".properties");
584 
585                                        if (configAsStream == null) {
586                                                throw SQLError.createSQLException(
587                                                                "Can't find configuration template named '"
588                                                                                + configName + "'",
589                                                                SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE);
590                                        }
591                                        configProps.load(configAsStream);
592                                } catch (IOException ioEx) {
593                                        throw SQLError.createSQLException(
594                                                        "Unable to load configuration template '"
595                                                                        + configName
596                                                                        + "' due to underlying IOException: "
597                                                                        + ioEx,
598                                                        SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE);
599                                }
600                        }
601 
602                        Iterator propsIter = urlProps.keySet().iterator();
603 
604                        while (propsIter.hasNext()) {
605                                String key = propsIter.next().toString();
606                                String property = urlProps.getProperty(key);
607                                configProps.setProperty(key, property);
608                        }
609 
610                        urlProps = configProps;
611                }
612 
613                // Properties passed in should override ones in URL
614 
615                if (defaults != null) {
616                        Iterator propsIter = defaults.keySet().iterator();
617 
618                        while (propsIter.hasNext()) {
619                                String key = propsIter.next().toString();
620                                String property = defaults.getProperty(key);
621                                urlProps.setProperty(key, property);
622                        }
623                }
624 
625                return urlProps;
626        }
627 
628        /**
629         * Returns the port number property
630         * 
631         * @param props
632         *            the properties to get the port number from
633         * 
634         * @return the port number
635         */
636        public int port(Properties props) {
637                return Integer.parseInt(props.getProperty(PORT_PROPERTY_KEY, "3306")); //$NON-NLS-1$ //$NON-NLS-2$
638        }
639 
640        /**
641         * Returns the given property from <code>props</code>
642         * 
643         * @param name
644         *            the property name
645         * @param props
646         *            the property instance to look in
647         * 
648         * @return the property value, or null if not found.
649         */
650        public String property(String name, Properties props) {
651                return props.getProperty(name);
652        }
653}

[all classes][com.mysql.jdbc]
EMMA 2.0.4217 (C) Vladimir Roubtsov