2009-12-03 37 views
7

Estoy escribiendo una herramienta de validación de bases de datos en Java y tengo pantallas de preferencias para que el usuario pueda definir sus conexiones a la base de datos. La herramienta debería poder hacer frente a DB2, Oracle, Postgresql y Mysql como mínimo.Encontrar controladores JDBC instalados

Lo que realmente me gustaría es poder presentar al usuario una lista de los controladores jdbc instalados como parte de este proceso.

¿Alguien puede proporcionar un fragmento de código para descubrir los controladores JDBC instalados?

Respuesta

9

Hasta el punto, necesita escanear todo el classpath (y subcarpetas) para las clases que implementan java.sql.Driver. De esta forma también cubrirá los controladores que son no cargados manualmente por Class#forName() o automágicamente por META-INF/services.

Aquí hay un ejemplo básico:

public static void main(String[] args) throws Exception { 
    List<Class<Driver>> drivers = findClassesImplementing(Driver.class); 
    System.out.println(drivers); 
}   

public static <T extends Object> List<Class<T>> findClassesImplementing(Class<T> cls) throws IOException { 
    List<Class<T>> classes = new ArrayList<Class<T>>(); 

    for (URL root : Collections.list(Thread.currentThread().getContextClassLoader().getResources(""))) { 
     for (File file : findFiles(new File(root.getFile()), ".+\\.jar$")) { 
      JarFile jarFile = new JarFile(file); 
      for (JarEntry jarEntry : Collections.list(jarFile.entries())) { 
       String name = jarEntry.getName(); 
       if (name.endsWith(".class")) try { 
        Class<?> found = Class.forName(name.replace("/", ".").replaceAll("\\.class$", "")); 
        if (cls.isAssignableFrom(found)) { 
         classes.add((Class<T>) found); 
        } 
       } catch (Throwable ignore) { 
        // No real class file, or JAR not in classpath, or missing links. 
       } 
      } 
     } 
    } 

    return classes; 
} 

public static List<File> findFiles(File directory, final String pattern) throws IOException { 
    File[] files = directory.listFiles(new FileFilter() { 
     public boolean accept(File file) { 
      return file.isDirectory() || file.getName().matches(pattern); 
     } 
    }); 

    List<File> found = new ArrayList<File>(files.length); 

    for (File file : files) { 
     if (file.isDirectory()) { 
      found.addAll(findFiles(file, pattern)); 
     } else { 
      found.add(file); 
     } 
    } 

    return found; 
} 

lugar también se puede considerar usar el Google Reflections API el que hace todo esto en una sola línea:

Set<Class<? extends Driver>> drivers = reflections.getSubTypesOf(Driver.class); 
+0

En esta solución, ¿no está ejecutando bloques estáticos en las clases que está probando? –

+0

Sí, serían ejecutados. No puedes evitar eso. – BalusC

+1

Thx bigtime, BalusC –

3

Esto debería ayudar:

java.sql.DriverManager.getDrivers() 
+6

ya que esta es mi humilde opinión incorrectamente aceptadas, lo único que haría enfatice más: esto funciona * solo * si los controladores están ** realmente ** cargados; ya sea manualmente por 'Clase # forName()' o automágicamente por 'META-INF/services'. Esto NO detecta controladores que * son * en classpath, pero que * no * están cargados. – BalusC

3
java.sql.DriverManager.getDrivers() 

no es todo.

A medida que el doc dice

recupera una enumeración con todos los controladores JDBC cargados actualmente la que el interlocutor actual tiene acceso.

Eso significa controladores cargados (con Class.forName()), no instalados (por ejemplo, disponibles a través de un JAR).

Normalmente, entregaría su software con todas las jarras de controladores JDBC que su programa puede funcionar. Dependiendo de a qué se conectará el usuario (oráculo, acceso, db2) el programa debe cargar el controlador apropiado.

+1

Tenía la impresión de que distribuir controladores de terceros en mis propios jarrones violaría los derechos de autor, o algo legal de todos modos –

+1

En realidad incluirá los controladores a los que se hace referencia mediante la propiedad del sistema 'jdbc.drivers' y los que están disponibles a través del proveedor de servicios (Mecanismo 'META-INF/services'). –

Cuestiones relacionadas