2009-12-03 11 views
7

私はJavaでデータベース検証ツールを作成しており、ユーザーがデータベース接続を定義できるように設定画面を持っています。このツールは、DB2、Oracle、Postgresql、およびMysqlに最小限に対応できる必要があります。インストールされたJDBCドライバを見つける

このプロセスの一部として、インストールされたjdbcドライバのリストをユーザに提示することができます。

インストールされたJDBCドライバを検出するためのコードスニペットを提供できますか?

答えて

9

java.sql.Driverを実装するクラスのクラスパス(およびサブフォルダ)全体をスキャンする必要があります。このようにして、ではなく、が手動でロードされたドライバをClass#forName()または自動でMETA-INF/servicesでカバーします。代わりに、あなたはまた、すべての単一のラインでこれを行いGoogle Reflections APIを使用するように考慮することができ

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

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

このソリューションでは、テストしているクラスで静的ブロックを実行していませんか? –

+0

はい、実行されます。あなたはそれを回避することはできません。 – BalusC

+1

Thx bigtime、BalusC –

3

これは役立つはず:

java.sql.DriverManager.getDrivers() 
+6

これは私だけだろう間違って受け入れ私見ですので

は、ここで基本的な例ですもっと重視してください:ドライバーが**実際に**搭載されている場合のみ、*動作します。手動で 'Class#forName()'で手動で実行するか、または 'META-INF/services'で自動的に実行します。これはクラスパスでは* *ロードされていない*ドライバを検出しません。 – BalusC

3
java.sql.DriverManager.getDrivers() 

は、すべてではありません。 docとして

は、現在の呼び出し元がアクセスを持っている へ の現在ロードされているすべてのJDBCドライバでEnumerationを取得しますと言います。 (JARを通して利用できると言う)がインストールされていない(Class.forNameの()付き)ロードされたドライバを、意味

通常、あなたのプログラムが動作することができるすべてのJDBCドライバ・ジャーを使ってソフトウェアを配布します。ユーザーが接続するもの(oracle、access、db2)に依存して、プログラムは適切なドライバをロードする必要があります。

+1

私は自分のjarファイルでサードパーティのドライバを配布することは著作権に違反するとか、法的に違法であるという印象を受けました –

+1

実際には、 'jdbc.drivers'システムプロパティから参照されるドライバと、サービスプロバイダ'META-INF/services')のメカニズムです。 –

関連する問題