private PageClassLoaderContext processUsingDependencies()

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


    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)
        {
            
            LOGGER.debug("Processing class {}", className);
            alreadyProcessed.add(className);
            
            // Sorting dependencies by type/alphabetically so we have consistent 
            // context trees between runs of the same webapp
            List<String> allNonPageDependencies = new ArrayList<>(
                    componentDependencyRegistry.getAllNonPageDependencies(className));
            Collections.sort(allNonPageDependencies, ClassNameComparator.INSTANCE);
            
            List<String> dependencies = new ArrayList<>(getDependenciesWithoutPages(className));
            Collections.sort(dependencies, ClassNameComparator.INSTANCE);
            
            // Process dependencies depth-first
            do
            {
                
                // Very unlikely to have infinite loops, but lets
                // avoid them anyway.
                int passes = 0;
                
                int contextsCreatedInThisPass = -1;
                
                while (contextsCreatedInThisPass < CONTEXTS_CREATED.get().get() && passes < 1000)
                {
                    
                    contextsCreatedInThisPass = CONTEXTS_CREATED.get().get();
            
                    for (String dependency : allNonPageDependencies)
                    {
                        // Avoid infinite recursion loops
                        if (!alreadyProcessed.contains(dependency)  
                                || root.findByClassName(dependency) == null)
                        {
                            processUsingDependencies(dependency, root, unknownContextProvider, 
                                    plasticProxyFactoryProvider, classesToInvalidate, alreadyProcessed, false);
                        }
                    }
                    
                }
                
            }
            while (!allNeededContextsAvailable(allNonPageDependencies));
            
            // Collect context dependencies
            Set<PageClassLoaderContext> contextDependencies = new HashSet<>();
            for (String dependency : allNonPageDependencies) 
            {
                PageClassLoaderContext dependencyContext = root.findByClassName(dependency);
                // Avoid infinite recursion loops
                if (multipleClassLoaders || !alreadyProcessed.contains(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);
                CONTEXTS_CREATED.get().incrementAndGet();
            }
            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);
                CONTEXTS_CREATED.get().incrementAndGet();
            }

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