    001// Licensed under the Apache License, Version 2.0 (the "License");
    002// you may not use this file except in compliance with the License.
    003// You may obtain a copy of the License at
    004//
    005// http://www.apache.org/licenses/LICENSE-2.0
    006//
    007// Unless required by applicable law or agreed to in writing, software
    008// distributed under the License is distributed on an "AS IS" BASIS,
    009// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    010// See the License for the specific language governing permissions and
    011// limitations under the License.
    012
    013package org.apache.tapestry5.modules;
    014
    015import java.util.List;
    016
    017import org.apache.tapestry5.SymbolConstants;
    018import org.apache.tapestry5.commons.MappedConfiguration;
    019import org.apache.tapestry5.commons.OrderedConfiguration;
    020import org.apache.tapestry5.http.TapestryHttpSymbolConstants;
    021import org.apache.tapestry5.internal.pageload.DefaultComponentRequestSelectorAnalyzer;
    022import org.apache.tapestry5.internal.pageload.DefaultComponentResourceLocator;
    023import org.apache.tapestry5.internal.pageload.PagePreloaderImpl;
    024import org.apache.tapestry5.internal.services.ComponentDependencyRegistry;
    025import org.apache.tapestry5.internal.services.ComponentDependencyRegistryImpl;
    026import org.apache.tapestry5.internal.services.ComponentInstantiatorSource;
    027import org.apache.tapestry5.internal.services.ComponentTemplateSource;
    028import org.apache.tapestry5.internal.services.ComponentTemplateSourceImpl;
    029import org.apache.tapestry5.internal.services.InternalComponentInvalidationEventHub;
    030import org.apache.tapestry5.internal.services.TemplateParser;
    031import org.apache.tapestry5.internal.services.assets.ResourceChangeTracker;
    032import org.apache.tapestry5.ioc.ServiceBinder;
    033import org.apache.tapestry5.ioc.annotations.Marker;
    034import org.apache.tapestry5.ioc.annotations.Startup;
    035import org.apache.tapestry5.ioc.annotations.Symbol;
    036import org.apache.tapestry5.ioc.services.ChainBuilder;
    037import org.apache.tapestry5.ioc.services.PerthreadManager;
    038import org.apache.tapestry5.services.ComponentClassResolver;
    039import org.apache.tapestry5.services.Core;
    040import org.apache.tapestry5.services.pageload.ComponentRequestSelectorAnalyzer;
    041import org.apache.tapestry5.services.pageload.ComponentResourceLocator;
    042import org.apache.tapestry5.services.pageload.PageCachingReferenceTypeService;
    043import org.apache.tapestry5.services.pageload.PageClassLoaderContextManager;
    044import org.apache.tapestry5.services.pageload.PageClassLoaderContextManagerImpl;
    045import org.apache.tapestry5.services.pageload.PagePreloader;
    046import org.apache.tapestry5.services.pageload.PreloaderMode;
    047import org.apache.tapestry5.services.pageload.ReferenceType;
    048import org.apache.tapestry5.services.templates.ComponentTemplateLocator;
    049
    050/**
    051 * @since 5.3
    052 */
    053@SuppressWarnings("deprecation")
    054@Marker(Core.class)
    055public class PageLoadModule
    056{
    057
    058    /**
    059     * Contributes factory defaults that may be overridden.
    060     */
    061    public static void contributeFactoryDefaults(MappedConfiguration<String, Object> configuration)
    062    {
    063        configuration.add(SymbolConstants.MULTIPLE_CLASSLOADERS, false);
    064        configuration.add(SymbolConstants.COMPONENT_DEPENDENCY_FILE, ComponentDependencyRegistry.FILENAME);
    065    }
    066
    067    public static void bind(ServiceBinder binder)
    068    {
    069        binder.bind(ComponentRequestSelectorAnalyzer.class, DefaultComponentRequestSelectorAnalyzer.class);
    070        binder.bind(ComponentResourceLocator.class, DefaultComponentResourceLocator.class);
    071        binder.bind(ComponentTemplateSource.class, ComponentTemplateSourceImpl.class);
    072        binder.bind(PagePreloader.class, PagePreloaderImpl.class);
    073        binder.bind(PageClassLoaderContextManager.class, PageClassLoaderContextManagerImpl.class);
    074    }
    075
    076    @Startup
    077    public static void preloadPages(PagePreloader preloader,
    078                                    @Symbol(SymbolConstants.PRELOADER_MODE)
    079                                    PreloaderMode mode,
    080                                    @Symbol(TapestryHttpSymbolConstants.PRODUCTION_MODE)
    081                                    boolean productionMode)
    082    {
    083        if (mode.isEnabledFor(productionMode))
    084        {
    085            preloader.preloadPages();
    086        }
    087    }
    088
    089    @Startup
    090    public void preloadPageClassLoaderContexts(
    091            PageClassLoaderContextManager pageClassLoaderContextManager,
    092            ComponentDependencyRegistry componentDependencyRegistry,
    093            @Symbol(SymbolConstants.PRODUCTION_MODE) boolean productionMode,
    094            @Symbol(SymbolConstants.MULTIPLE_CLASSLOADERS) boolean multipleClassLoaders)
    095    {
    096        if (!productionMode && multipleClassLoaders)
    097        {
    098            // Preload the page activation context tree for the already known classes
    099            for (int i = 0; i < 5; i++)
    100            {
    101                for (String className : componentDependencyRegistry.getClassNames())
    102                {
    103                    pageClassLoaderContextManager.get(className);
    104                }
    105            }
    106        }
    107    }
    108
    109    public static PageCachingReferenceTypeService buildPageCachingReferenceTypeService(
    110            List<PageCachingReferenceTypeService> configuration,
    111            ChainBuilder chainBuilder)
    112    {
    113        return chainBuilder.build(PageCachingReferenceTypeService.class, configuration);
    114    }
    115
    116    public static void contributePageCachingReferenceTypeService(
    117            OrderedConfiguration<PageCachingReferenceTypeService> configuration)
    118    {
    119        configuration.add("Fallback", p -> ReferenceType.SOFT, "after:*");
    120    }
    121
    122    public static ComponentDependencyRegistry buildComponentDependencyRegistry(
    123            InternalComponentInvalidationEventHub internalComponentInvalidationEventHub,
    124            ResourceChangeTracker resourceChangeTracker,
    125            ComponentTemplateSource componentTemplateSource,
    126            PageClassLoaderContextManager pageClassLoaderContextManager,
    127            ComponentInstantiatorSource componentInstantiatorSource,
    128            ComponentClassResolver componentClassResolver,
    129            TemplateParser templateParser,
    130            ComponentTemplateLocator componentTemplateLocator,
    131            PerthreadManager perthreadManager,
    132            @Symbol(SymbolConstants.COMPONENT_DEPENDENCY_FILE) String componentDependencyFile,
    133            @Symbol(SymbolConstants.PRODUCTION_MODE) boolean productionMode)
    134    {
    135        ComponentDependencyRegistryImpl componentDependencyRegistry =
    136                new ComponentDependencyRegistryImpl(
    137                        pageClassLoaderContextManager,
    138                        componentInstantiatorSource.getProxyFactory().getPlasticManager(),
    139                        componentClassResolver,
    140                        templateParser,
    141                        componentTemplateLocator,
    142                        componentDependencyFile,
    143                        productionMode);
    144        componentDependencyRegistry.listen(internalComponentInvalidationEventHub);
    145        componentDependencyRegistry.listen(resourceChangeTracker);
    146        componentDependencyRegistry.listen(componentTemplateSource.getInvalidationEventHub());
    147        // TODO: remove
    148        componentDependencyRegistry.setupThreadCleanup(perthreadManager);
    149        return componentDependencyRegistry;
    150    }
    151
    152}