~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/ikvm/openjdk/java/sql/DriverManager.java

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
 
3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 
4
 *
 
5
 * This code is free software; you can redistribute it and/or modify it
 
6
 * under the terms of the GNU General Public License version 2 only, as
 
7
 * published by the Free Software Foundation.  Oracle designates this
 
8
 * particular file as subject to the "Classpath" exception as provided
 
9
 * by Oracle in the LICENSE file that accompanied this code.
 
10
 *
 
11
 * This code is distributed in the hope that it will be useful, but WITHOUT
 
12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 
13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 
14
 * version 2 for more details (a copy is included in the LICENSE file that
 
15
 * accompanied this code).
 
16
 *
 
17
 * You should have received a copy of the GNU General Public License version
 
18
 * 2 along with this work; if not, write to the Free Software Foundation,
 
19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 
20
 *
 
21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 
22
 * or visit www.oracle.com if you need additional information or have any
 
23
 * questions.
 
24
 */
 
25
 
 
26
package java.sql;
 
27
 
 
28
import ikvm.internal.CallerID;
 
29
import java.util.Iterator;
 
30
import java.sql.Driver;
 
31
import java.util.ServiceLoader;
 
32
import java.security.AccessController;
 
33
import java.security.PrivilegedAction;
 
34
 
 
35
 
 
36
/**
 
37
 * <P>The basic service for managing a set of JDBC drivers.<br>
 
38
 * <B>NOTE:</B> The {@link <code>DataSource</code>} interface, new in the
 
39
 * JDBC 2.0 API, provides another way to connect to a data source.
 
40
 * The use of a <code>DataSource</code> object is the preferred means of
 
41
 * connecting to a data source.
 
42
 *
 
43
 * <P>As part of its initialization, the <code>DriverManager</code> class will
 
44
 * attempt to load the driver classes referenced in the "jdbc.drivers"
 
45
 * system property. This allows a user to customize the JDBC Drivers
 
46
 * used by their applications. For example in your
 
47
 * ~/.hotjava/properties file you might specify:
 
48
 * <pre>
 
49
 * <CODE>jdbc.drivers=foo.bah.Driver:wombat.sql.Driver:bad.taste.ourDriver</CODE>
 
50
 * </pre>
 
51
 *<P> The <code>DriverManager</code> methods <code>getConnection</code> and
 
52
 * <code>getDrivers</code> have been enhanced to support the Java Standard Edition
 
53
 * <a href="../../../technotes/guides/jar/jar.html#Service%20Provider">Service Provider</a> mechanism. JDBC 4.0 Drivers must
 
54
 * include the file <code>META-INF/services/java.sql.Driver</code>. This file contains the name of the JDBC drivers
 
55
 * implementation of <code>java.sql.Driver</code>.  For example, to load the <code>my.sql.Driver</code> class,
 
56
 * the <code>META-INF/services/java.sql.Driver</code> file would contain the entry:
 
57
 * <pre>
 
58
 * <code>my.sql.Driver</code>
 
59
 * </pre>
 
60
 *
 
61
 * <P>Applications no longer need to explictly load JDBC drivers using <code>Class.forName()</code>. Existing programs
 
62
 * which currently load JDBC drivers using <code>Class.forName()</code> will continue to work without
 
63
 * modification.
 
64
 *
 
65
 * <P>When the method <code>getConnection</code> is called,
 
66
 * the <code>DriverManager</code> will attempt to
 
67
 * locate a suitable driver from amongst those loaded at
 
68
 * initialization and those loaded explicitly using the same classloader
 
69
 * as the current applet or application.
 
70
 *
 
71
 * <P>
 
72
 * Starting with the Java 2 SDK, Standard Edition, version 1.3, a
 
73
 * logging stream can be set only if the proper
 
74
 * permission has been granted.  Normally this will be done with
 
75
 * the tool PolicyTool, which can be used to grant <code>permission
 
76
 * java.sql.SQLPermission "setLog"</code>.
 
77
 * @see Driver
 
78
 * @see Connection
 
79
 */
 
80
public class DriverManager {
 
81
 
 
82
 
 
83
    /**
 
84
     * The <code>SQLPermission</code> constant that allows the
 
85
     * setting of the logging stream.
 
86
     * @since 1.3
 
87
     */
 
88
    final static SQLPermission SET_LOG_PERMISSION =
 
89
        new SQLPermission("setLog");
 
90
 
 
91
    //--------------------------JDBC 2.0-----------------------------
 
92
 
 
93
    /**
 
94
     * Retrieves the log writer.
 
95
     *
 
96
     * The <code>getLogWriter</code> and <code>setLogWriter</code>
 
97
     * methods should be used instead
 
98
     * of the <code>get/setlogStream</code> methods, which are deprecated.
 
99
     * @return a <code>java.io.PrintWriter</code> object
 
100
     * @see #setLogWriter
 
101
     * @since 1.2
 
102
     */
 
103
    public static java.io.PrintWriter getLogWriter() {
 
104
            return logWriter;
 
105
    }
 
106
 
 
107
    /**
 
108
     * Sets the logging/tracing <code>PrintWriter</code> object
 
109
     * that is used by the <code>DriverManager</code> and all drivers.
 
110
     * <P>
 
111
     * There is a minor versioning problem created by the introduction
 
112
     * of the method <code>setLogWriter</code>.  The
 
113
     * method <code>setLogWriter</code> cannot create a <code>PrintStream</code> object
 
114
     * that will be returned by <code>getLogStream</code>---the Java platform does
 
115
     * not provide a backward conversion.  As a result, a new application
 
116
     * that uses <code>setLogWriter</code> and also uses a JDBC 1.0 driver that uses
 
117
     * <code>getLogStream</code> will likely not see debugging information written
 
118
     * by that driver.
 
119
     *<P>
 
120
     * Starting with the Java 2 SDK, Standard Edition, version 1.3 release, this method checks
 
121
     * to see that there is an <code>SQLPermission</code> object before setting
 
122
     * the logging stream.  If a <code>SecurityManager</code> exists and its
 
123
     * <code>checkPermission</code> method denies setting the log writer, this
 
124
     * method throws a <code>java.lang.SecurityException</code>.
 
125
     *
 
126
     * @param out the new logging/tracing <code>PrintStream</code> object;
 
127
     *      <code>null</code> to disable logging and tracing
 
128
     * @throws SecurityException
 
129
     *    if a security manager exists and its
 
130
     *    <code>checkPermission</code> method denies
 
131
     *    setting the log writer
 
132
     *
 
133
     * @see SecurityManager#checkPermission
 
134
     * @see #getLogWriter
 
135
     * @since 1.2
 
136
     */
 
137
    public static void setLogWriter(java.io.PrintWriter out) {
 
138
 
 
139
        SecurityManager sec = System.getSecurityManager();
 
140
        if (sec != null) {
 
141
            sec.checkPermission(SET_LOG_PERMISSION);
 
142
        }
 
143
            logStream = null;
 
144
            logWriter = out;
 
145
    }
 
146
 
 
147
 
 
148
    //---------------------------------------------------------------
 
149
 
 
150
    /**
 
151
     * Attempts to establish a connection to the given database URL.
 
152
     * The <code>DriverManager</code> attempts to select an appropriate driver from
 
153
     * the set of registered JDBC drivers.
 
154
     *
 
155
     * @param url a database url of the form
 
156
     * <code> jdbc:<em>subprotocol</em>:<em>subname</em></code>
 
157
     * @param info a list of arbitrary string tag/value pairs as
 
158
     * connection arguments; normally at least a "user" and
 
159
     * "password" property should be included
 
160
     * @return a Connection to the URL
 
161
     * @exception SQLException if a database access error occurs
 
162
     */
 
163
    @ikvm.internal.HasCallerID
 
164
    public static Connection getConnection(String url,
 
165
        java.util.Properties info) throws SQLException {
 
166
 
 
167
        // Gets the classloader of the code that called this method, may
 
168
        // be null.
 
169
        ClassLoader callerCL = CallerID.getCallerID().getCallerClassLoader();
 
170
 
 
171
        return (getConnection(url, info, callerCL));
 
172
    }
 
173
 
 
174
    /**
 
175
     * Attempts to establish a connection to the given database URL.
 
176
     * The <code>DriverManager</code> attempts to select an appropriate driver from
 
177
     * the set of registered JDBC drivers.
 
178
     *
 
179
     * @param url a database url of the form
 
180
     * <code>jdbc:<em>subprotocol</em>:<em>subname</em></code>
 
181
     * @param user the database user on whose behalf the connection is being
 
182
     *   made
 
183
     * @param password the user's password
 
184
     * @return a connection to the URL
 
185
     * @exception SQLException if a database access error occurs
 
186
     */
 
187
    @ikvm.internal.HasCallerID
 
188
    public static Connection getConnection(String url,
 
189
        String user, String password) throws SQLException {
 
190
        java.util.Properties info = new java.util.Properties();
 
191
 
 
192
        // Gets the classloader of the code that called this method, may
 
193
        // be null.
 
194
        ClassLoader callerCL = CallerID.getCallerID().getCallerClassLoader();
 
195
 
 
196
        if (user != null) {
 
197
            info.put("user", user);
 
198
        }
 
199
        if (password != null) {
 
200
            info.put("password", password);
 
201
        }
 
202
 
 
203
        return (getConnection(url, info, callerCL));
 
204
    }
 
205
 
 
206
    /**
 
207
     * Attempts to establish a connection to the given database URL.
 
208
     * The <code>DriverManager</code> attempts to select an appropriate driver from
 
209
     * the set of registered JDBC drivers.
 
210
     *
 
211
     * @param url a database url of the form
 
212
     *  <code> jdbc:<em>subprotocol</em>:<em>subname</em></code>
 
213
     * @return a connection to the URL
 
214
     * @exception SQLException if a database access error occurs
 
215
     */
 
216
    @ikvm.internal.HasCallerID
 
217
    public static Connection getConnection(String url)
 
218
        throws SQLException {
 
219
 
 
220
        java.util.Properties info = new java.util.Properties();
 
221
 
 
222
        // Gets the classloader of the code that called this method, may
 
223
        // be null.
 
224
        ClassLoader callerCL = CallerID.getCallerID().getCallerClassLoader();
 
225
 
 
226
        return (getConnection(url, info, callerCL));
 
227
    }
 
228
 
 
229
    /**
 
230
     * Attempts to locate a driver that understands the given URL.
 
231
     * The <code>DriverManager</code> attempts to select an appropriate driver from
 
232
     * the set of registered JDBC drivers.
 
233
     *
 
234
     * @param url a database URL of the form
 
235
     *     <code>jdbc:<em>subprotocol</em>:<em>subname</em></code>
 
236
     * @return a <code>Driver</code> object representing a driver
 
237
     * that can connect to the given URL
 
238
     * @exception SQLException if a database access error occurs
 
239
     */
 
240
    @ikvm.internal.HasCallerID
 
241
    public static Driver getDriver(String url)
 
242
        throws SQLException {
 
243
        java.util.Vector drivers = null;
 
244
 
 
245
        println("DriverManager.getDriver(\"" + url + "\")");
 
246
 
 
247
        if (!initialized) {
 
248
            initialize();
 
249
        }
 
250
 
 
251
        synchronized (DriverManager.class){
 
252
            // use the read copy of the drivers vector
 
253
            drivers = readDrivers;
 
254
        }
 
255
 
 
256
        // Gets the classloader of the code that called this method, may
 
257
        // be null.
 
258
        ClassLoader callerCL = CallerID.getCallerID().getCallerClassLoader();
 
259
 
 
260
        // Walk through the loaded drivers attempting to locate someone
 
261
        // who understands the given URL.
 
262
        for (int i = 0; i < drivers.size(); i++) {
 
263
            DriverInfo di = (DriverInfo)drivers.elementAt(i);
 
264
            // If the caller does not have permission to load the driver then
 
265
            // skip it.
 
266
            if ( getCallerClass(callerCL, di.driverClassName ) !=
 
267
                 di.driverClass ) {
 
268
                println("    skipping: " + di);
 
269
                continue;
 
270
            }
 
271
            try {
 
272
                println("    trying " + di);
 
273
                if (di.driver.acceptsURL(url)) {
 
274
                    // Success!
 
275
                    println("getDriver returning " + di);
 
276
                    return (di.driver);
 
277
                }
 
278
            } catch (SQLException ex) {
 
279
                // Drop through and try the next driver.
 
280
            }
 
281
        }
 
282
 
 
283
        println("getDriver: no suitable driver");
 
284
        throw new SQLException("No suitable driver", "08001");
 
285
    }
 
286
 
 
287
 
 
288
    /**
 
289
     * Registers the given driver with the <code>DriverManager</code>.
 
290
     * A newly-loaded driver class should call
 
291
     * the method <code>registerDriver</code> to make itself
 
292
     * known to the <code>DriverManager</code>.
 
293
     *
 
294
     * @param driver the new JDBC Driver that is to be registered with the
 
295
     *               <code>DriverManager</code>
 
296
     * @exception SQLException if a database access error occurs
 
297
     */
 
298
    public static synchronized void registerDriver(java.sql.Driver driver)
 
299
        throws SQLException {
 
300
        if (!initialized) {
 
301
            initialize();
 
302
        }
 
303
 
 
304
        DriverInfo di = new DriverInfo();
 
305
 
 
306
        di.driver = driver;
 
307
        di.driverClass = driver.getClass();
 
308
        di.driverClassName = di.driverClass.getName();
 
309
 
 
310
        // Not Required -- drivers.addElement(di);
 
311
 
 
312
        writeDrivers.addElement(di);
 
313
        println("registerDriver: " + di);
 
314
 
 
315
        /* update the read copy of drivers vector */
 
316
        readDrivers = (java.util.Vector) writeDrivers.clone();
 
317
 
 
318
    }
 
319
 
 
320
    /**
 
321
     * Drops a driver from the <code>DriverManager</code>'s list.
 
322
     *  Applets can only deregister drivers from their own classloaders.
 
323
     *
 
324
     * @param driver the JDBC Driver to drop
 
325
     * @exception SQLException if a database access error occurs
 
326
     */
 
327
    @ikvm.internal.HasCallerID
 
328
    public static synchronized void deregisterDriver(Driver driver)
 
329
        throws SQLException {
 
330
        // Gets the classloader of the code that called this method,
 
331
        // may be null.
 
332
        ClassLoader callerCL = CallerID.getCallerID().getCallerClassLoader();
 
333
        println("DriverManager.deregisterDriver: " + driver);
 
334
 
 
335
        // Walk through the loaded drivers.
 
336
        int i;
 
337
        DriverInfo di = null;
 
338
        for (i = 0; i < writeDrivers.size(); i++) {
 
339
            di = (DriverInfo)writeDrivers.elementAt(i);
 
340
            if (di.driver == driver) {
 
341
                break;
 
342
            }
 
343
        }
 
344
        // If we can't find the driver just return.
 
345
        if (i >= writeDrivers.size()) {
 
346
            println("    couldn't find driver to unload");
 
347
            return;
 
348
        }
 
349
 
 
350
        // If the caller does not have permission to load the driver then
 
351
        // throw a security exception.
 
352
        if (getCallerClass(callerCL, di.driverClassName ) != di.driverClass ) {
 
353
            throw new SecurityException();
 
354
        }
 
355
 
 
356
        // Remove the driver.  Other entries in drivers get shuffled down.
 
357
        writeDrivers.removeElementAt(i);
 
358
 
 
359
        /* update the read copy of drivers vector */
 
360
        readDrivers = (java.util.Vector) writeDrivers.clone();
 
361
    }
 
362
 
 
363
    /**
 
364
     * Retrieves an Enumeration with all of the currently loaded JDBC drivers
 
365
     * to which the current caller has access.
 
366
     *
 
367
     * <P><B>Note:</B> The classname of a driver can be found using
 
368
     * <CODE>d.getClass().getName()</CODE>
 
369
     *
 
370
     * @return the list of JDBC Drivers loaded by the caller's class loader
 
371
     */
 
372
    @ikvm.internal.HasCallerID
 
373
    public static java.util.Enumeration<Driver> getDrivers() {
 
374
        java.util.Vector<Driver> result = new java.util.Vector<Driver>();
 
375
        java.util.Vector drivers = null;
 
376
 
 
377
        if (!initialized) {
 
378
            initialize();
 
379
        }
 
380
 
 
381
        synchronized (DriverManager.class){
 
382
            // use the readcopy of drivers
 
383
            drivers  = readDrivers;
 
384
       }
 
385
 
 
386
        // Gets the classloader of the code that called this method, may
 
387
        // be null.
 
388
        ClassLoader callerCL = CallerID.getCallerID().getCallerClassLoader();
 
389
 
 
390
        // Walk through the loaded drivers.
 
391
        for (int i = 0; i < drivers.size(); i++) {
 
392
            DriverInfo di = (DriverInfo)drivers.elementAt(i);
 
393
            // If the caller does not have permission to load the driver then
 
394
            // skip it.
 
395
            if ( getCallerClass(callerCL, di.driverClassName ) != di.driverClass ) {
 
396
                println("    skipping: " + di);
 
397
                continue;
 
398
            }
 
399
            result.addElement(di.driver);
 
400
        }
 
401
 
 
402
        return (result.elements());
 
403
    }
 
404
 
 
405
 
 
406
    /**
 
407
     * Sets the maximum time in seconds that a driver will wait
 
408
     * while attempting to connect to a database.
 
409
     *
 
410
     * @param seconds the login time limit in seconds; zero means there is no limit
 
411
     * @see #getLoginTimeout
 
412
     */
 
413
    public static void setLoginTimeout(int seconds) {
 
414
        loginTimeout = seconds;
 
415
    }
 
416
 
 
417
    /**
 
418
     * Gets the maximum time in seconds that a driver can wait
 
419
     * when attempting to log in to a database.
 
420
     *
 
421
     * @return the driver login time limit in seconds
 
422
     * @see #setLoginTimeout
 
423
     */
 
424
    public static int getLoginTimeout() {
 
425
        return (loginTimeout);
 
426
    }
 
427
 
 
428
    /**
 
429
     * Sets the logging/tracing PrintStream that is used
 
430
     * by the <code>DriverManager</code>
 
431
     * and all drivers.
 
432
     *<P>
 
433
     * In the Java 2 SDK, Standard Edition, version 1.3 release, this method checks
 
434
     * to see that there is an <code>SQLPermission</code> object before setting
 
435
     * the logging stream.  If a <code>SecurityManager</code> exists and its
 
436
     * <code>checkPermission</code> method denies setting the log writer, this
 
437
     * method throws a <code>java.lang.SecurityException</code>.
 
438
     *
 
439
     * @param out the new logging/tracing PrintStream; to disable, set to <code>null</code>
 
440
     * @deprecated
 
441
     * @throws SecurityException if a security manager exists and its
 
442
     *    <code>checkPermission</code> method denies setting the log stream
 
443
     *
 
444
     * @see SecurityManager#checkPermission
 
445
     * @see #getLogStream
 
446
     */
 
447
    public static void setLogStream(java.io.PrintStream out) {
 
448
 
 
449
        SecurityManager sec = System.getSecurityManager();
 
450
        if (sec != null) {
 
451
            sec.checkPermission(SET_LOG_PERMISSION);
 
452
        }
 
453
 
 
454
        logStream = out;
 
455
        if ( out != null )
 
456
            logWriter = new java.io.PrintWriter(out);
 
457
        else
 
458
            logWriter = null;
 
459
    }
 
460
 
 
461
    /**
 
462
     * Retrieves the logging/tracing PrintStream that is used by the <code>DriverManager</code>
 
463
     * and all drivers.
 
464
     *
 
465
     * @return the logging/tracing PrintStream; if disabled, is <code>null</code>
 
466
     * @deprecated
 
467
     * @see #setLogStream
 
468
     */
 
469
    public static java.io.PrintStream getLogStream() {
 
470
        return logStream;
 
471
    }
 
472
 
 
473
    /**
 
474
     * Prints a message to the current JDBC log stream.
 
475
     *
 
476
     * @param message a log or tracing message
 
477
     */
 
478
    public static void println(String message) {
 
479
        synchronized (logSync) {
 
480
            if (logWriter != null) {
 
481
                logWriter.println(message);
 
482
 
 
483
                // automatic flushing is never enabled, so we must do it ourselves
 
484
                logWriter.flush();
 
485
            }
 
486
        }
 
487
    }
 
488
 
 
489
    //------------------------------------------------------------------------
 
490
 
 
491
    // Returns the class object that would be created if the code calling the
 
492
    // driver manager had loaded the driver class, or null if the class
 
493
    // is inaccessible.
 
494
    private static Class getCallerClass(ClassLoader callerClassLoader,
 
495
                                        String driverClassName) {
 
496
        Class callerC = null;
 
497
 
 
498
        try {
 
499
            callerC = Class.forName(driverClassName, true, callerClassLoader);
 
500
        }
 
501
        catch (Exception ex) {
 
502
            callerC = null;           // being very careful
 
503
        }
 
504
 
 
505
        return callerC;
 
506
    }
 
507
 
 
508
    private static void loadInitialDrivers() {
 
509
        String drivers;
 
510
        try {
 
511
            drivers = (String)  AccessController.doPrivileged(new PrivilegedAction() {
 
512
                public Object run() {
 
513
                    return System.getProperty("jdbc.drivers");
 
514
                }
 
515
            });
 
516
        } catch (Exception ex) {
 
517
            drivers = null;
 
518
        }
 
519
        // If the driver is packaged as a Service Provider, load it.
 
520
        // Get all the drivers through the classloader
 
521
        // exposed as a java.sql.Driver.class service.
 
522
        // ServiceLoader.load() replaces the sun.misc.Providers()
 
523
 
 
524
        AccessController.doPrivileged(new PrivilegedAction() {
 
525
            public Object run() {
 
526
 
 
527
                ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);
 
528
                Iterator driversIterator = loadedDrivers.iterator();
 
529
 
 
530
                /* Load these drivers, so that they can be instantiated.
 
531
                 * It may be the case that the driver class may not be there
 
532
                 * i.e. there may be a packaged driver with the service class
 
533
                 * as implementation of java.sql.Driver but the actual class
 
534
                 * may be missing. In that case a java.util.ServiceConfigurationError
 
535
                 * will be thrown at runtime by the VM trying to locate
 
536
                 * and load the service.
 
537
                 *
 
538
                 * Adding a try catch block to catch those runtime errors
 
539
                 * if driver not available in classpath but it's
 
540
                 * packaged as service and that service is there in classpath.
 
541
                 */
 
542
                try{
 
543
                    while(driversIterator.hasNext()) {
 
544
                        println(" Loading done by the java.util.ServiceLoader :  "+driversIterator.next());
 
545
                    }
 
546
                } catch(Throwable t) {
 
547
                // Do nothing
 
548
                }
 
549
                return null;
 
550
            }
 
551
        });
 
552
 
 
553
        println("DriverManager.initialize: jdbc.drivers = " + drivers);
 
554
        if (drivers == null) {
 
555
            return;
 
556
        }
 
557
        while (drivers.length() != 0) {
 
558
            int x = drivers.indexOf(':');
 
559
            String driver;
 
560
            if (x < 0) {
 
561
                driver = drivers;
 
562
                drivers = "";
 
563
            } else {
 
564
                driver = drivers.substring(0, x);
 
565
                drivers = drivers.substring(x+1);
 
566
            }
 
567
            if (driver.length() == 0) {
 
568
                continue;
 
569
            }
 
570
            try {
 
571
                println("DriverManager.Initialize: loading " + driver);
 
572
                Class.forName(driver, true,
 
573
                              ClassLoader.getSystemClassLoader());
 
574
            } catch (Exception ex) {
 
575
                println("DriverManager.Initialize: load failed: " + ex);
 
576
            }
 
577
        }
 
578
    }
 
579
 
 
580
 
 
581
    //  Worker method called by the public getConnection() methods.
 
582
    private static Connection getConnection(
 
583
        String url, java.util.Properties info, ClassLoader callerCL) throws SQLException {
 
584
        java.util.Vector drivers = null;
 
585
        /*
 
586
         * When callerCl is null, we should check the application's
 
587
         * (which is invoking this class indirectly)
 
588
         * classloader, so that the JDBC driver class outside rt.jar
 
589
         * can be loaded from here.
 
590
         */
 
591
        synchronized(DriverManager.class) {
 
592
          // synchronize loading of the correct classloader.
 
593
          if(callerCL == null) {
 
594
              callerCL = Thread.currentThread().getContextClassLoader();
 
595
           }
 
596
        }
 
597
 
 
598
        if(url == null) {
 
599
            throw new SQLException("The url cannot be null", "08001");
 
600
        }
 
601
 
 
602
        println("DriverManager.getConnection(\"" + url + "\")");
 
603
 
 
604
        if (!initialized) {
 
605
            initialize();
 
606
        }
 
607
 
 
608
        synchronized (DriverManager.class){
 
609
            // use the readcopy of drivers
 
610
            drivers = readDrivers;
 
611
        }
 
612
 
 
613
        // Walk through the loaded drivers attempting to make a connection.
 
614
        // Remember the first exception that gets raised so we can reraise it.
 
615
        SQLException reason = null;
 
616
        for (int i = 0; i < drivers.size(); i++) {
 
617
            DriverInfo di = (DriverInfo)drivers.elementAt(i);
 
618
 
 
619
            // If the caller does not have permission to load the driver then
 
620
            // skip it.
 
621
            if ( getCallerClass(callerCL, di.driverClassName ) != di.driverClass ) {
 
622
                println("    skipping: " + di);
 
623
                continue;
 
624
            }
 
625
            try {
 
626
                println("    trying " + di);
 
627
                Connection result = di.driver.connect(url, info);
 
628
                if (result != null) {
 
629
                    // Success!
 
630
                    println("getConnection returning " + di);
 
631
                    return (result);
 
632
                }
 
633
            } catch (SQLException ex) {
 
634
                if (reason == null) {
 
635
                    reason = ex;
 
636
                }
 
637
            }
 
638
        }
 
639
 
 
640
        // if we got here nobody could connect.
 
641
        if (reason != null)    {
 
642
            println("getConnection failed: " + reason);
 
643
            throw reason;
 
644
        }
 
645
 
 
646
        println("getConnection: no suitable driver found for "+ url);
 
647
        throw new SQLException("No suitable driver found for "+ url, "08001");
 
648
    }
 
649
 
 
650
 
 
651
    // Class initialization.
 
652
    static void initialize() {
 
653
        if (initialized) {
 
654
            return;
 
655
        }
 
656
        initialized = true;
 
657
        loadInitialDrivers();
 
658
        println("JDBC DriverManager initialized");
 
659
    }
 
660
 
 
661
    /* Prevent the DriverManager class from being instantiated. */
 
662
    private DriverManager(){}
 
663
 
 
664
    /* write copy of the drivers vector */
 
665
    private static java.util.Vector writeDrivers = new java.util.Vector();
 
666
 
 
667
    /* write copy of the drivers vector */
 
668
    private static java.util.Vector readDrivers = new java.util.Vector();
 
669
 
 
670
    private static int loginTimeout = 0;
 
671
    private static java.io.PrintWriter logWriter = null;
 
672
    private static java.io.PrintStream logStream = null;
 
673
    private static boolean initialized = false;
 
674
 
 
675
    private static Object logSync = new Object();
 
676
 
 
677
}
 
678
 
 
679
// DriverInfo is a package-private support class.
 
680
class DriverInfo {
 
681
    Driver         driver;
 
682
    Class          driverClass;
 
683
    String         driverClassName;
 
684
 
 
685
    public String toString() {
 
686
        return ("driver[className=" + driverClassName + "," + driver + "]");
 
687
    }
 
688
}