Finding Installed JDBC Drivers

后端 未结 3 1059
逝去的感伤
逝去的感伤 2021-01-02 15:53

I\'m writing a database validation tool in Java and have preference screens so the user can define their database connections. The tool should be able to cope with DB2, Orac

3条回答
  •  情歌与酒
    2021-01-02 16:37

    To the point, you need to scan the entire classpath (and subfolders) for classes implementing java.sql.Driver. This way you will also cover drivers which are not loaded manually by Class#forName() or automagically by META-INF/services.

    Here's a basic example:

    public static void main(String[] args) throws Exception {
        List> drivers = findClassesImplementing(Driver.class);
        System.out.println(drivers);
    }        
    
    public static  List> findClassesImplementing(Class cls) throws IOException {
        List> classes = new ArrayList>();
    
        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) found);
                        }
                    } catch (Throwable ignore) {
                        // No real class file, or JAR not in classpath, or missing links.
                    }
                }
            }
        }
    
        return classes;
    }
    
    public static List 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 found = new ArrayList(files.length);
    
        for (File file : files) {
            if (file.isDirectory()) {
                found.addAll(findFiles(file, pattern));
            } else {
                found.add(file);
            }
        }
    
        return found;
    }
    

    Instead you can also consider to use the Google Reflections API which does this all in a single line:

    Set> drivers = reflections.getSubTypesOf(Driver.class);
    

提交回复
热议问题