View Javadoc
1   /*
2    * This file is part of dependency-check-core.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   *
16   * Copyright (c) 2014 Jeremy Long. All Rights Reserved.
17   */
18  package org.owasp.dependencycheck.data.nvdcve;
19  
20  import org.slf4j.Logger;
21  import org.slf4j.LoggerFactory;
22  
23  import java.io.File;
24  import java.net.MalformedURLException;
25  import java.net.URL;
26  import java.net.URLClassLoader;
27  import java.security.AccessController;
28  import java.security.PrivilegedAction;
29  import java.sql.Driver;
30  import java.sql.DriverManager;
31  import java.sql.SQLException;
32  import java.util.ArrayList;
33  import java.util.List;
34  
35  /**
36   * DriverLoader is a utility class that is used to load database drivers.
37   *
38   * @author Jeremy Long
39   */
40  public final class DriverLoader {
41  
42      /**
43       * The logger.
44       */
45      private static final Logger LOGGER = LoggerFactory.getLogger(DriverLoader.class);
46  
47      /**
48       * Private constructor for a utility class.
49       */
50      private DriverLoader() {
51      }
52  
53      /**
54       * Loads the specified class using the system class loader and registers the driver with the driver manager.
55       *
56       * @param className the fully qualified name of the desired class
57       * @return the loaded Driver
58       * @throws DriverLoadException thrown if the driver cannot be loaded
59       */
60      public static Driver load(String className) throws DriverLoadException {
61          final ClassLoader loader = DriverLoader.class.getClassLoader(); //ClassLoader.getSystemClassLoader();
62          return load(className, loader);
63      }
64  
65      /**
66       * Loads the specified class by registering the supplied paths to the class loader and then registers the driver with the
67       * driver manager. The pathToDriver argument is added to the class loader so that an external driver can be loaded. Note, the
68       * pathToDriver can contain a semi-colon separated list of paths so any dependencies can be added as needed. If a path in the
69       * pathToDriver argument is a directory all files in the directory are added to the class path.
70       *
71       * @param className the fully qualified name of the desired class
72       * @param pathToDriver the path to the JAR file containing the driver; note, this can be a semi-colon separated list of paths
73       * @return the loaded Driver
74       * @throws DriverLoadException thrown if the driver cannot be loaded
75       */
76      public static Driver load(String className, String pathToDriver) throws DriverLoadException {
77          final URLClassLoader parent = (URLClassLoader) ClassLoader.getSystemClassLoader();
78          final List<URL> urls = new ArrayList<URL>();
79          final String[] paths = pathToDriver.split(File.pathSeparator);
80          for (String path : paths) {
81              final File file = new File(path);
82              if (file.isDirectory()) {
83                  final File[] files = file.listFiles();
84                  if (files != null) {
85                      for (File f : files) {
86                          try {
87                              urls.add(f.toURI().toURL());
88                          } catch (MalformedURLException ex) {
89                              LOGGER.debug("Unable to load database driver '{}'; invalid path provided '{}'",
90                                      className, f.getAbsoluteFile(), ex);
91                              throw new DriverLoadException("Unable to load database driver. Invalid path provided", ex);
92                          }
93                      }
94                  }
95              } else if (file.exists()) {
96                  try {
97                      urls.add(file.toURI().toURL());
98                  } catch (MalformedURLException ex) {
99                      LOGGER.debug("Unable to load database driver '{}'; invalid path provided '{}'",
100                             className, file.getAbsoluteFile(), ex);
101                     throw new DriverLoadException("Unable to load database driver. Invalid path provided", ex);
102                 }
103             }
104         }
105         final URLClassLoader loader = AccessController.doPrivileged(new PrivilegedAction<URLClassLoader>() {
106             @Override
107             public URLClassLoader run() {
108                 return new URLClassLoader(urls.toArray(new URL[urls.size()]), parent);
109             }
110         });
111 
112         return load(className, loader);
113     }
114 
115     /**
116      * Loads the specified class using the supplied class loader and registers the driver with the driver manager.
117      *
118      * @param className the fully qualified name of the desired class
119      * @param loader the class loader to use when loading the driver
120      * @return the loaded Driver
121      * @throws DriverLoadException thrown if the driver cannot be loaded
122      */
123     private static Driver load(String className, ClassLoader loader) throws DriverLoadException {
124         try {
125             final Class c = Class.forName(className, true, loader);
126             //final Class c = loader.loadClass(className);
127             final Driver driver = (Driver) c.newInstance();
128             final Driver shim = new DriverShim(driver);
129             //using the DriverShim to get around the fact that the DriverManager won't register a driver not in the base class path
130             DriverManager.registerDriver(shim);
131             return shim;
132         } catch (ClassNotFoundException ex) {
133             final String msg = String.format("Unable to load database driver '%s'", className);
134             LOGGER.debug(msg, ex);
135             throw new DriverLoadException(msg, ex);
136         } catch (InstantiationException ex) {
137             final String msg = String.format("Unable to load database driver '%s'", className);
138             LOGGER.debug(msg, ex);
139             throw new DriverLoadException(msg, ex);
140         } catch (IllegalAccessException ex) {
141             final String msg = String.format("Unable to load database driver '%s'", className);
142             LOGGER.debug(msg, ex);
143             throw new DriverLoadException(msg, ex);
144         } catch (SQLException ex) {
145             final String msg = String.format("Unable to load database driver '%s'", className);
146             LOGGER.debug(msg, ex);
147             throw new DriverLoadException(msg, ex);
148         }
149     }
150 }