2009-12-03 83 views
7

我正在用Java編寫一個數據庫驗證工具,並具有首選項屏幕,因此用戶可以定義它們的數據庫連接。該工具應該至少能夠處理DB2,Oracle,Postgresql和Mysql。查找已安裝的JDBC驅動程序

我真正想要的是能夠向用戶顯示安裝的jdbc驅動程序列表,作爲此過程的一部分。

任何人都可以提供用於發現已安裝的JDBC驅動程序的代碼片段嗎?

回答

9

至此,您需要掃描整個類路徑(和子文件夾)以實現java.sql.Driver的類。這樣,您還將涵蓋的驅動程序是而不是Class#forName()手動加載或由META-INF/services自動加載。

這裏有一個基本的例子:

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; 
} 

相反,你也可以考慮使用哪個,這一切在一個單一的線Google Reflections API

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

在這個解決方案中,你不是在正在測試的類上執行靜態塊嗎? – 2009-12-03 15:31:09

+0

是的,他們會被執行。你無法繞過那個。 – BalusC 2009-12-03 15:37:58

+1

Thx bigtime,BalusC – 2009-12-03 17:48:50

3

這應有助於:

java.sql.DriverManager.getDrivers() 
+6

由於這是恕我直言不正確接受,我只是會強調更多:這隻適用*如果驅動程序實際上**加載;可以通過'Class#forName()'手動地或'META-INF/services'自動地進行。這不會檢測哪些*是在classpath中的驅動程序,但它們是* not *加載的。 – BalusC 2009-12-03 14:03:28

3
java.sql.DriverManager.getDrivers() 

還不是全部。

由於doc

檢索與所有的 當前已加載JDBC驅動程序 枚舉當前調用者可以訪問。

這意味着加載的驅動程序(與Class.forName()),未安裝(通過JAR可用)。

通常情況下,您需要爲您的軟件提供您的程序可以工作的所有JDBC驅動程序罐。依賴於用戶將連接到(oracle,access,db2)程序必須加載相應的驅動程序。

+1

我的印象是,在我自己的罐子裏分發第三方驅動程序會違反版權 - 或者任何合法的東西 – 2009-12-03 13:43:37

+1

實際上它會包含通過'jdbc.drivers'系統屬性引用的驅動程序和通過服務提供程序提供的驅動程序( META-INF/services')機制。 – 2009-12-03 13:44:19