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.Order; 035import org.apache.tapestry5.ioc.annotations.Startup; 036import org.apache.tapestry5.ioc.annotations.Symbol; 037import org.apache.tapestry5.ioc.services.ChainBuilder; 038import org.apache.tapestry5.ioc.services.PerthreadManager; 039import org.apache.tapestry5.services.ComponentClassResolver; 040import org.apache.tapestry5.services.Core; 041import org.apache.tapestry5.services.pageload.ComponentRequestSelectorAnalyzer; 042import org.apache.tapestry5.services.pageload.ComponentResourceLocator; 043import org.apache.tapestry5.services.pageload.PageCachingReferenceTypeService; 044import org.apache.tapestry5.services.pageload.PageClassLoaderContextManager; 045import org.apache.tapestry5.services.pageload.PageClassLoaderContextManagerImpl; 046import org.apache.tapestry5.services.pageload.PagePreloader; 047import org.apache.tapestry5.services.pageload.PreloaderMode; 048import org.apache.tapestry5.services.pageload.ReferenceType; 049import org.apache.tapestry5.services.templates.ComponentTemplateLocator; 050 051/** 052 * @since 5.3 053 */ 054@SuppressWarnings("deprecation") 055@Marker(Core.class) 056public class PageLoadModule 057{ 058 059 /** 060 * Contributes factory defaults that may be overridden. 061 */ 062 public static void contributeFactoryDefaults(MappedConfiguration<String, Object> configuration) 063 { 064 configuration.add(SymbolConstants.MULTIPLE_CLASSLOADERS, false); 065 configuration.add(SymbolConstants.COMPONENT_DEPENDENCY_FILE, ComponentDependencyRegistry.FILENAME); 066 } 067 068 public static void bind(ServiceBinder binder) 069 { 070 binder.bind(ComponentRequestSelectorAnalyzer.class, DefaultComponentRequestSelectorAnalyzer.class); 071 binder.bind(ComponentResourceLocator.class, DefaultComponentResourceLocator.class); 072 binder.bind(ComponentTemplateSource.class, ComponentTemplateSourceImpl.class); 073 binder.bind(PagePreloader.class, PagePreloaderImpl.class); 074 binder.bind(PageClassLoaderContextManager.class, PageClassLoaderContextManagerImpl.class); 075 } 076 077 @Startup 078 public static void preloadPages(PagePreloader preloader, 079 @Symbol(SymbolConstants.PRELOADER_MODE) 080 PreloaderMode mode, 081 @Symbol(TapestryHttpSymbolConstants.PRODUCTION_MODE) 082 boolean productionMode) 083 { 084 if (mode.isEnabledFor(productionMode)) 085 { 086 preloader.preloadPages(); 087 } 088 } 089 090 @Startup 091 @Order("before:*") 092 public void preloadPageClassLoaderContexts( 093 PageClassLoaderContextManager pageClassLoaderContextManager, 094 ComponentDependencyRegistry componentDependencyRegistry, 095 @Symbol(SymbolConstants.PRODUCTION_MODE) boolean productionMode, 096 @Symbol(SymbolConstants.MULTIPLE_CLASSLOADERS) boolean multipleClassLoaders) 097 { 098 if (!productionMode && multipleClassLoaders) 099 { 100 // Preload the page activation context tree for the already known classes 101 for (int i = 0; i < 5; i++) 102 { 103 for (String className : componentDependencyRegistry.getClassNames()) 104 { 105 pageClassLoaderContextManager.get(className); 106 } 107 } 108 } 109 // Preload the dependency information for all pages 110 // when in production mode. Without that, exceptions during 111 // page assembly will occurr. This should add just a few 112 // seconds to page initialization. If it takes too long, 113 // we can create a version of preload() that accepts a boolean 114 // parameter defining whether templates should be parsed or not 115 // (the exception occurrs when a superclass isn't loaded 116 // and transformed before a subclass) 117 else if (productionMode) 118 { 119 pageClassLoaderContextManager.preload(); 120 } 121 } 122 123 public static PageCachingReferenceTypeService buildPageCachingReferenceTypeService( 124 List<PageCachingReferenceTypeService> configuration, 125 ChainBuilder chainBuilder) 126 { 127 return chainBuilder.build(PageCachingReferenceTypeService.class, configuration); 128 } 129 130 public static void contributePageCachingReferenceTypeService( 131 OrderedConfiguration<PageCachingReferenceTypeService> configuration) 132 { 133 configuration.add("Fallback", p -> ReferenceType.SOFT, "after:*"); 134 } 135 136 public static ComponentDependencyRegistry buildComponentDependencyRegistry( 137 InternalComponentInvalidationEventHub internalComponentInvalidationEventHub, 138 ResourceChangeTracker resourceChangeTracker, 139 ComponentTemplateSource componentTemplateSource, 140 PageClassLoaderContextManager pageClassLoaderContextManager, 141 ComponentInstantiatorSource componentInstantiatorSource, 142 ComponentClassResolver componentClassResolver, 143 TemplateParser templateParser, 144 ComponentTemplateLocator componentTemplateLocator, 145 PerthreadManager perthreadManager, 146 @Symbol(SymbolConstants.COMPONENT_DEPENDENCY_FILE) String componentDependencyFile, 147 @Symbol(SymbolConstants.PRODUCTION_MODE) boolean productionMode) 148 { 149 ComponentDependencyRegistryImpl componentDependencyRegistry = 150 new ComponentDependencyRegistryImpl( 151 pageClassLoaderContextManager, 152 componentInstantiatorSource.getProxyFactory().getPlasticManager(), 153 componentClassResolver, 154 templateParser, 155 componentTemplateLocator, 156 componentDependencyFile, 157 productionMode); 158 componentDependencyRegistry.listen(internalComponentInvalidationEventHub); 159 componentDependencyRegistry.listen(resourceChangeTracker); 160 componentDependencyRegistry.listen(componentTemplateSource.getInvalidationEventHub()); 161 // TODO: remove 162 componentDependencyRegistry.setupThreadCleanup(perthreadManager); 163 return componentDependencyRegistry; 164 } 165 166}