private PageClassLoaderContext processUsingDependencies()

in tapestry-core/src/main/java/org/apache/tapestry5/services/pageload/PageClassLoaderContextManagerImpl.java [210:324]


    private PageClassLoaderContext processUsingDependencies(
            String className, 
            PageClassLoaderContext root, 
            Supplier<PageClassLoaderContext> unknownContextProvider, 
            Function<ClassLoader, PlasticProxyFactory> plasticProxyFactoryProvider, 
            Set<String> classesToInvalidate,
            Set<String> alreadyProcessed,
            boolean processCircularDependencies) 
    {
        PageClassLoaderContext context = root.findByClassName(className);
        if (context == null)
        {
            
            // Class isn't in a controlled package, so it doesn't get transformed
            // and should go for the root context, which is never thrown out.
            if (!root.getPlasticManager().shouldInterceptClassLoading(className))
            {
                context = root;
            } else {
                if (
                        !componentDependencyRegistry.contains(className) ||
                        !multipleClassLoaders
                        // TODO: review this
//                        && componentDependencyRegistry.getDependents(className).isEmpty()
                        )
                {
                    context = unknownContextProvider.get();
                }
                else 
                {

                    alreadyProcessed.add(className);
                    
                    // Sorting dependencies alphabetically so we have consistent results.
                    List<String> dependencies = new ArrayList<>(getDependenciesWithoutPages(className));
                    Collections.sort(dependencies);
                    
                    // Process dependencies depth-first
                    for (String dependency : dependencies)
                    {
                        // Avoid infinite recursion loops
                        if (!alreadyProcessed.contains(dependency)/* && 
                                !circularDependencies.contains(dependency)*/)
                        {
                            processUsingDependencies(dependency, root, unknownContextProvider, 
                                    plasticProxyFactoryProvider, classesToInvalidate, alreadyProcessed, false);
                        }
                    }
                    
                    // Collect context dependencies
                    Set<PageClassLoaderContext> contextDependencies = new HashSet<>();
                    for (String dependency : dependencies) 
                    {
                        PageClassLoaderContext dependencyContext = root.findByClassName(dependency);
                        if (dependencyContext == null)
                        {
                            dependencyContext = processUsingDependencies(dependency, root, unknownContextProvider,
                                    plasticProxyFactoryProvider, classesToInvalidate, alreadyProcessed);

                        }
                        if (!dependencyContext.isRoot())
                        {
                            contextDependencies.add(dependencyContext);
                        }
                    }
                    
                    if (contextDependencies.size() == 0)
                    {
                        context = new PageClassLoaderContext(
                                getContextName(className), 
                                root, 
                                Collections.singleton(className), 
                                plasticProxyFactoryProvider.apply(root.getClassLoader()),
                                this::get);
                    }
                    else 
                    {
                        PageClassLoaderContext parentContext;
                        if (contextDependencies.size() == 1)
                        {
                            parentContext = contextDependencies.iterator().next();
                        }
                        else
                        {
                            parentContext = merge(contextDependencies, plasticProxyFactoryProvider, root, classesToInvalidate);
                        }
                        context = new PageClassLoaderContext(
                                getContextName(className), 
                                parentContext, 
                                Collections.singleton(className), 
                                plasticProxyFactoryProvider.apply(parentContext.getClassLoader()),
                                this::get);
                    }
                    
                    context.getParent().addChild(context);
                    
                    // Ensure non-page class is initialized in the correct context and classloader.
                    // Pages get their own context and classloader, so this initialization
                    // is both non-needed and a cause for an NPE if it happens.
                    if (!componentClassResolver.isPage(className)
                            || componentDependencyRegistry.getDependencies(className, DependencyType.USAGE).isEmpty())
                    {
                        loadClass(className, context);
                    }

                    LOGGER.debug("New context: {}", context);
                    
                }
            }
            
        }
        context.addClass(className);
        
        return context;
    }