Skip to content

Polish QuarkusClassLoaderHandler and FastPathResolver.#894

Merged
lukehutch merged 1 commit intoclassgraph:latestfrom
michael-simons:quarkus316andhigher
Nov 11, 2024
Merged

Polish QuarkusClassLoaderHandler and FastPathResolver.#894
lukehutch merged 1 commit intoclassgraph:latestfrom
michael-simons:quarkus316andhigher

Conversation

@michael-simons
Copy link
Contributor

This is a follow up on issue #891 and the preceding PR #893 and brings two changes:

  • The QuarkusClassLoaderHandler is a bit more explicit now about how the elements returned from the class loader are treated
  • The FastPathResolver can be simplified using only one pattern

The latter was discovered while trying to get the custom URL scheme quarkus: that the Quarkus class loader uses for in-memory classes to work.

Ultimately, the work on using those in-memory classes, that are usually transformed classes such as session proxies, has been abandoned due to the fact that the current ClassGraph infrastructure can basically deal only with Jar and related entries, or directories.
To make the Quarkus in-memory classes work one would need to map them to ultimately into a Jar file and use an additional custom URL scheme, to "download" them again.
The alternative is additional implementations of ClasspathElement, but that would require a change on public API and this not only quite a bit out of my comfort zone, but also in all probability, not worth the effort.

I am happy to pick it if there's ever be a need, though.

The changes I had in addition (but those are only barely minimum, they won't work, as the scanner thinks that the urls are paths and does not use openStream or similar):

    private static void findClasspathOrderForQuarkusClassloader(final ClassLoader classLoader,
                                                                final ClasspathOrder classpathOrder, final ScanSpec scanSpec, final LogNode log) {

        Collection<Object> elements = findQuarkusClassLoaderElements(classLoader, classpathOrder);

        for (final Object element : elements) {
            final String elementClassName = element.getClass().getName();
            final String fieldName = PRE_311_RESOURCE_BASED_ELEMENTS.get(elementClassName);
            if (fieldName != null) {
                classpathOrder.addClasspathEntry(classpathOrder.reflectionUtils.getFieldVal(false, element, fieldName),
                        classLoader, scanSpec, log);
            } else if("io.quarkus.bootstrap.classloading.MemoryClassPathElement".equals(elementClassName)) {
               handleInMemoryClassPathElements(classLoader, classpathOrder, scanSpec, log, element);
            } else {
                final Object rootPath = classpathOrder.reflectionUtils.invokeMethod(false, element, "getRoot");
                if (rootPath instanceof Path) {
                    classpathOrder.addClasspathEntry(rootPath, classLoader, scanSpec, log);
                }
            }
        }
    }

    @SuppressWarnings("unchecked")
    private static void handleInMemoryClassPathElements(final ClassLoader classLoader,
                                                        final ClasspathOrder classpathOrder, final ScanSpec scanSpec, final LogNode log, Object element) {
        // Those will be transformed classes, such as session proxies etc.
        Collection<String> resourceNames = (Collection<String>) classpathOrder.reflectionUtils.invokeMethod(false, element, "getProvidedResources");
        if (resourceNames == null) {
            return;
        }
        for (String resourceName : resourceNames) {
            Object resource = classpathOrder.reflectionUtils.invokeMethod(false, element, "getResource", String.class, resourceName);
            if (resource == null) {
                continue;
            }
            URL url = (URL) classpathOrder.reflectionUtils.invokeMethod(false, resource, "getUrl");
            classpathOrder.addClasspathEntryObject(url, classLoader, scanSpec, log);
        }
    }

@michael-simons
Copy link
Contributor Author

Of course I forget my main point: I would be quite happy if my previous change and potentially this additional change could go out as a release. Thank you! 🙇

This is a follow up on issue classgraph#891 and the preceding PR classgraph#893 and brings two changes:

* The `QuarkusClassLoaderHandler` is a bit more explicit now about how the elements returned from the class loader are treated
* The `FastPathResolver` can be simplified using only one pattern
@lukehutch
Copy link
Member

@michael-simons LGTM, I will push out a release later today -- sorry that I was offline for a few days! (I'll try to quickly get a Narcissus release before then, so ClassGraph can depend on the new version.)

@lukehutch lukehutch merged commit e7bb9f0 into classgraph:latest Nov 11, 2024
@michael-simons
Copy link
Contributor Author

Nice, thank you. I set up the Narcissus pipelines and opened a PR there.

@michael-simons michael-simons deleted the quarkus316andhigher branch November 12, 2024 04:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants