liquibase-core/src/main/java/liquibase/resource/ClassLoaderResourceAccessor.java
protected List<Path> findRootPaths(ClassLoader classLoader) throws Exception {
        if (classLoader == null) {
            return new ArrayList<>();

        }

        Logger logger = Scope.getCurrentScope().getLog(getClass());

        List<URL> returnUrls = new ArrayList<>();
        if (classLoader instanceof URLClassLoader) {
            returnUrls.addAll(CollectionUtil.createIfNull(Arrays.asList(((URLClassLoader) classLoader).getURLs())));
        } else {
            logger.info("Found non-URL ClassLoader classloader " + classLoader.toString() + ". Liquibase will try to figure out now to load resources from it, some may be missed. Consider using a custom ClassLoaderResourceAccessor subclass.");
            Set<String> seenUrls = new HashSet<>(); //need to track externalForm as a string to avoid java problem with URL.equals making a network call

            Enumeration<URL> emptyPathUrls = classLoader.getResources("");
            while (emptyPathUrls.hasMoreElements()) {
                URL url = emptyPathUrls.nextElement();
                if (seenUrls.add(url.toExternalForm())) {
                    returnUrls.add(url);
                }
            }

            Enumeration<URL> metaInfoPathUrls = classLoader.getResources("META-INF");
            while (metaInfoPathUrls.hasMoreElements()) {
                String originalUrl = metaInfoPathUrls.nextElement().toExternalForm();
                String finalUrl = originalUrl.replaceFirst("/META-INF", "");
                if (finalUrl.startsWith("jar:")) {
                    if (finalUrl.endsWith("!")) {
                        finalUrl = finalUrl.replaceFirst("^jar:", "").replaceFirst("!$", "");
                    } else {
                        logger.warning("ClassLoader URL " + finalUrl + " starts with jar: but does not end with !, don't knnow how to handle it. Skipping");
                        continue;
                    }
                }

                URL finalUrlObj = new URL(finalUrl);
                if (seenUrls.add(finalUrlObj.toExternalForm())) {
                    returnUrls.add(finalUrlObj);
                }
            }

        }

        List<Path> returnPaths = new ArrayList<>();
        for (URL url : returnUrls) {
            Path path = rootUrlToPath(url);
            if (path != null) {
                logger.fine("Found classloader root at " + path.toString());
                returnPaths.add(path);
            }
        }
        return returnPaths;
    }
protected List<Path> findRootPaths(ClassLoader classLoader) throws Exception {
        if (classLoader == null) {
            return new ArrayList<>();

        }

        Logger logger = Scope.getCurrentScope().getLog(getClass());

        List<URL> returnUrls = new ArrayList<>();
        if (classLoader instanceof URLClassLoader) {
            returnUrls.addAll(CollectionUtil.createIfNull(Arrays.asList(((URLClassLoader) classLoader).getURLs())));
        } else {
            logger.info("Found non-URL ClassLoader classloader " + classLoader.toString() + ". Liquibase will try to figure out now to load resources from it, some may be missed. Consider using a custom ClassLoaderResourceAccessor subclass.");
            Set<String> seenUrls = new HashSet<>(); //need to track externalForm as a string to avoid java problem with URL.equals making a network call

            Enumeration<URL> emptyPathUrls = classLoader.getResources("");
            while (emptyPathUrls.hasMoreElements()) {
                URL url = emptyPathUrls.nextElement();
                if (seenUrls.add(url.toExternalForm())) {
                    returnUrls.add(url);
                }
            }

            Enumeration<URL> metaInfoPathUrls = classLoader.getResources("META-INF");
            while (metaInfoPathUrls.hasMoreElements()) {
                String originalUrl = metaInfoPathUrls.nextElement().toExternalForm();
                String finalUrl = originalUrl.replaceFirst("/META-INF", "");
                if (finalUrl.startsWith("jar:")) {
                    if (finalUrl.endsWith("!")) {
                        finalUrl = finalUrl.replaceFirst("^jar:", "").replaceFirst("!$", "");
                    } else {
                        logger.warning("ClassLoader URL " + finalUrl + " starts with jar: but does not end with !, don't knnow how to handle it. Skipping");
                        continue;
                    }
                }

                URL finalUrlObj = new URL(finalUrl);
                if (seenUrls.add(finalUrlObj.toExternalForm())) {
                    returnUrls.add(finalUrlObj);
                }
            }

        }

        List<Path> returnPaths = new ArrayList<>();
        for (URL url : returnUrls) {
            Path path = rootUrlToPath(url);
            if (path != null) {
                logger.fine("Found classloader root at " + path.toString());
                returnPaths.add(path);
            }
        }
        return returnPaths;
    }
Called by constructor to create all the root paths from the given classloader.
Works best if the passed classLoader is a {@link URLClassLoader} because it can get the root file/dirs directly.
If it is not a URLClassLoader, it still attempts to find files by looking up base packages and MANIFEST.MF files.
This may miss some roots, however, and so if you are not using a URLClassLoader consider using a custom subclass.