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}