EMMA Coverage Report (generated Fri May 26 15:35:26 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)77%  (499/647)82%  (115.5/141)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class NonRegisteringDriver100% (1/1)69%  (11/16)77%  (499/647)82%  (115.5/141)
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)63%  (32/51)78%  (7/9)
parseHostPortPair (String): String [] 100% (1/1)73%  (40/55)77%  (10/13)
parseURL (String, Properties): Properties 100% (1/1)77%  (287/374)84%  (65.5/78)
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("@MYSQL_CJ_MAJOR_VERSION@"); //$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("@MYSQL_CJ_MINOR_VERSION@"); //$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 new SQLException(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, this);
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 new SQLException(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://")) { //$NON-NLS-1$
444 
445                        return null;
446                }
447 
448                /*
449                 * Parse parameters after the ? in the URL and remove them from the
450                 * original URL.
451                 */
452                int index = url.indexOf("?"); //$NON-NLS-1$
453 
454                if (index != -1) {
455                        String paramString = url.substring(index + 1, url.length());
456                        url = url.substring(0, index);
457 
458                        StringTokenizer queryParams = new StringTokenizer(paramString, "&"); //$NON-NLS-1$
459 
460                        while (queryParams.hasMoreTokens()) {
461                                String parameterValuePair = queryParams.nextToken();
462                                
463                                int indexOfEquals = StringUtils.indexOfIgnoreCase(0, parameterValuePair, "=");
464 
465                                String parameter = null;
466                                String value = null;
467                                
468                                if (indexOfEquals != -1) {
469                                        parameter = parameterValuePair.substring(0, indexOfEquals);
470                                        
471                                        if (indexOfEquals + 1 < parameterValuePair.length()) {
472                                                value = parameterValuePair.substring(indexOfEquals + 1);
473                                        }
474                                }
475                                
476                                if ((value != null && value.length() > 0) && 
477                                                (parameter != null && parameter.length() > 0)) {
478                                        try {
479                                                urlProps.put(parameter, URLDecoder.decode(value,
480                                                                "UTF-8"));
481                                        } catch (UnsupportedEncodingException badEncoding) {
482                                                // punt
483                                                urlProps.put(parameter, URLDecoder.decode(value));
484                                        } catch (NoSuchMethodError nsme) {
485                                                // punt again
486                                                urlProps.put(parameter,  URLDecoder.decode(value));
487                                        }
488                                }
489                        }
490                }
491 
492                url = url.substring(13);
493 
494                String hostStuff = null;
495 
496                int slashIndex = url.indexOf("/"); //$NON-NLS-1$
497 
498                if (slashIndex != -1) {
499                        hostStuff = url.substring(0, slashIndex);
500 
501                        if ((slashIndex + 1) < url.length()) {
502                                urlProps.put(DBNAME_PROPERTY_KEY, //$NON-NLS-1$
503                                                url.substring((slashIndex + 1), url.length()));
504                        }
505                } else {
506                        return null;
507                }
508 
509                if ((hostStuff != null) && (hostStuff.length() > 0)) {
510                        urlProps.put(HOST_PROPERTY_KEY, hostStuff); //$NON-NLS-1$
511                }
512 
513                String propertiesTransformClassName = urlProps
514                                .getProperty(PROPERTIES_TRANSFORM_KEY);
515 
516                if (propertiesTransformClassName != null) {
517                        try {
518                                ConnectionPropertiesTransform propTransformer = (ConnectionPropertiesTransform) Class
519                                                .forName(propertiesTransformClassName).newInstance();
520 
521                                urlProps = propTransformer.transformProperties(urlProps);
522                        } catch (InstantiationException e) {
523                                throw new SQLException(
524                                                "Unable to create properties transform instance '"
525                                                                + propertiesTransformClassName
526                                                                + "' due to underlying exception: "
527                                                                + e.toString(),
528                                                SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE);
529                        } catch (IllegalAccessException e) {
530                                throw new SQLException(
531                                                "Unable to create properties transform instance '"
532                                                                + propertiesTransformClassName
533                                                                + "' due to underlying exception: "
534                                                                + e.toString(),
535                                                SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE);
536                        } catch (ClassNotFoundException e) {
537                                throw new SQLException(
538                                                "Unable to create properties transform instance '"
539                                                                + propertiesTransformClassName
540                                                                + "' due to underlying exception: "
541                                                                + e.toString(),
542                                                SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE);
543                        }
544                }
545 
546                // If we use a config, it actually should get overridden by anything in
547                // the URL or passed-in properties
548 
549                String configNames = null;
550 
551                if (defaults != null) {
552                        configNames = defaults.getProperty(USE_CONFIG_PROPERTY_KEY);
553                }
554 
555                if (configNames == null) {
556                        configNames = urlProps.getProperty(USE_CONFIG_PROPERTY_KEY);
557                }
558 
559                if (configNames != null) {
560                        List splitNames = StringUtils.split(configNames, ",", true);
561 
562                        Properties configProps = new Properties();
563 
564                        Iterator namesIter = splitNames.iterator();
565 
566                        while (namesIter.hasNext()) {
567                                String configName = (String) namesIter.next();
568 
569                                try {
570                                        InputStream configAsStream = getClass()
571                                                        .getResourceAsStream(
572                                                                        "configs/" + configName + ".properties");
573 
574                                        if (configAsStream == null) {
575                                                throw new SQLException(
576                                                                "Can't find configuration template named '"
577                                                                                + configName + "'",
578                                                                SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE);
579                                        }
580                                        configProps.load(configAsStream);
581                                } catch (IOException ioEx) {
582                                        throw new SQLException(
583                                                        "Unable to load configuration template '"
584                                                                        + configName
585                                                                        + "' due to underlying IOException: "
586                                                                        + ioEx,
587                                                        SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE);
588                                }
589                        }
590 
591                        Iterator propsIter = urlProps.keySet().iterator();
592 
593                        while (propsIter.hasNext()) {
594                                String key = propsIter.next().toString();
595                                String property = urlProps.getProperty(key);
596                                configProps.setProperty(key, property);
597                        }
598 
599                        urlProps = configProps;
600                }
601 
602                // Properties passed in should override ones in URL
603 
604                if (defaults != null) {
605                        Iterator propsIter = defaults.keySet().iterator();
606 
607                        while (propsIter.hasNext()) {
608                                String key = propsIter.next().toString();
609                                String property = defaults.getProperty(key);
610                                urlProps.setProperty(key, property);
611                        }
612                }
613 
614                return urlProps;
615        }
616 
617        /**
618         * Returns the port number property
619         * 
620         * @param props
621         *            the properties to get the port number from
622         * 
623         * @return the port number
624         */
625        public int port(Properties props) {
626                return Integer.parseInt(props.getProperty(PORT_PROPERTY_KEY, "3306")); //$NON-NLS-1$ //$NON-NLS-2$
627        }
628 
629        /**
630         * Returns the given property from <code>props</code>
631         * 
632         * @param name
633         *            the property name
634         * @param props
635         *            the property instance to look in
636         * 
637         * @return the property value, or null if not found.
638         */
639        public String property(String name, Properties props) {
640                return props.getProperty(name);
641        }
642}

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