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.io.IOException; 016import java.io.InputStream; 017import java.lang.annotation.Annotation; 018import java.math.BigDecimal; 019import java.math.BigInteger; 020import java.net.URL; 021import java.text.DateFormat; 022import java.text.SimpleDateFormat; 023import java.util.Calendar; 024import java.util.Collection; 025import java.util.Date; 026import java.util.List; 027import java.util.Locale; 028import java.util.Map; 029import java.util.Properties; 030import java.util.Set; 031import java.util.regex.Pattern; 032 033import org.apache.tapestry5.Asset; 034import org.apache.tapestry5.BindingConstants; 035import org.apache.tapestry5.Block; 036import org.apache.tapestry5.ComponentParameterConstants; 037import org.apache.tapestry5.ComponentResources; 038import org.apache.tapestry5.EventContext; 039import org.apache.tapestry5.Field; 040import org.apache.tapestry5.FieldValidationSupport; 041import org.apache.tapestry5.FieldValidator; 042import org.apache.tapestry5.MarkupWriter; 043import org.apache.tapestry5.MetaDataConstants; 044import org.apache.tapestry5.NullFieldStrategy; 045import org.apache.tapestry5.PersistenceConstants; 046import org.apache.tapestry5.PropertyOverrides; 047import org.apache.tapestry5.Renderable; 048import org.apache.tapestry5.SelectModel; 049import org.apache.tapestry5.StreamResponse; 050import org.apache.tapestry5.SymbolConstants; 051import org.apache.tapestry5.Translator; 052import org.apache.tapestry5.ValidationDecorator; 053import org.apache.tapestry5.Validator; 054import org.apache.tapestry5.ValueEncoder; 055import org.apache.tapestry5.ajax.MultiZoneUpdate; 056import org.apache.tapestry5.alerts.AlertManager; 057import org.apache.tapestry5.annotations.ActivationRequestParameter; 058import org.apache.tapestry5.annotations.BindParameter; 059import org.apache.tapestry5.annotations.ContentType; 060import org.apache.tapestry5.annotations.DiscardAfter; 061import org.apache.tapestry5.annotations.HeartbeatDeferred; 062import org.apache.tapestry5.annotations.Import; 063import org.apache.tapestry5.annotations.Meta; 064import org.apache.tapestry5.annotations.MixinAfter; 065import org.apache.tapestry5.annotations.PageActivationContext; 066import org.apache.tapestry5.annotations.PageAttached; 067import org.apache.tapestry5.annotations.PageDetached; 068import org.apache.tapestry5.annotations.PageLoaded; 069import org.apache.tapestry5.annotations.PageReset; 070import org.apache.tapestry5.annotations.Path; 071import org.apache.tapestry5.annotations.Persist; 072import org.apache.tapestry5.annotations.Secure; 073import org.apache.tapestry5.annotations.Service; 074import org.apache.tapestry5.annotations.SessionAttribute; 075import org.apache.tapestry5.annotations.UnknownActivationContextCheck; 076import org.apache.tapestry5.annotations.WhitelistAccessOnly; 077import org.apache.tapestry5.beaneditor.DataTypeConstants; 078import org.apache.tapestry5.beaneditor.Validate; 079import org.apache.tapestry5.beanmodel.internal.services.BeanModelSourceImpl; 080import org.apache.tapestry5.beanmodel.internal.services.PropertyConduitSourceImpl; 081import org.apache.tapestry5.beanmodel.services.BeanModelSource; 082import org.apache.tapestry5.beanmodel.services.PropertyConduitSource; 083import org.apache.tapestry5.commons.AnnotationProvider; 084import org.apache.tapestry5.commons.Configuration; 085import org.apache.tapestry5.commons.Location; 086import org.apache.tapestry5.commons.MappedConfiguration; 087import org.apache.tapestry5.commons.Messages; 088import org.apache.tapestry5.commons.ObjectLocator; 089import org.apache.tapestry5.commons.ObjectProvider; 090import org.apache.tapestry5.commons.OrderedConfiguration; 091import org.apache.tapestry5.commons.Resource; 092import org.apache.tapestry5.commons.internal.BasicDataTypeAnalyzers; 093import org.apache.tapestry5.commons.internal.services.AnnotationDataTypeAnalyzer; 094import org.apache.tapestry5.commons.internal.services.DefaultDataTypeAnalyzer; 095import org.apache.tapestry5.commons.internal.services.StringInterner; 096import org.apache.tapestry5.commons.internal.services.StringInternerImpl; 097import org.apache.tapestry5.commons.services.Coercion; 098import org.apache.tapestry5.commons.services.CoercionTuple; 099import org.apache.tapestry5.commons.services.DataTypeAnalyzer; 100import org.apache.tapestry5.commons.services.InvalidationEventHub; 101import org.apache.tapestry5.commons.services.PlasticProxyFactory; 102import org.apache.tapestry5.commons.services.PropertyAccess; 103import org.apache.tapestry5.commons.services.TypeCoercer; 104import org.apache.tapestry5.commons.util.AvailableValues; 105import org.apache.tapestry5.commons.util.CollectionFactory; 106import org.apache.tapestry5.commons.util.StrategyRegistry; 107import org.apache.tapestry5.commons.util.VersionUtils; 108import org.apache.tapestry5.corelib.data.SecureOption; 109import org.apache.tapestry5.grid.GridConstants; 110import org.apache.tapestry5.grid.GridDataSource; 111import org.apache.tapestry5.http.Link; 112import org.apache.tapestry5.http.TapestryHttpConstants; 113import org.apache.tapestry5.http.TapestryHttpSymbolConstants; 114import org.apache.tapestry5.http.internal.TapestryHttpInternalConstants; 115import org.apache.tapestry5.http.internal.TapestryHttpInternalSymbols; 116import org.apache.tapestry5.http.modules.TapestryHttpModule; 117import org.apache.tapestry5.http.services.ApplicationGlobals; 118import org.apache.tapestry5.http.services.ApplicationInitializer; 119import org.apache.tapestry5.http.services.ApplicationInitializerFilter; 120import org.apache.tapestry5.http.services.Context; 121import org.apache.tapestry5.http.services.Dispatcher; 122import org.apache.tapestry5.http.services.HttpServletRequestFilter; 123import org.apache.tapestry5.http.services.Request; 124import org.apache.tapestry5.http.services.RequestFilter; 125import org.apache.tapestry5.http.services.RequestGlobals; 126import org.apache.tapestry5.http.services.RequestHandler; 127import org.apache.tapestry5.http.services.Response; 128import org.apache.tapestry5.http.services.Session; 129import org.apache.tapestry5.internal.ComponentOverrideImpl; 130import org.apache.tapestry5.internal.DefaultNullFieldStrategy; 131import org.apache.tapestry5.internal.DefaultValueLabelProvider; 132import org.apache.tapestry5.internal.InternalConstants; 133import org.apache.tapestry5.internal.InternalSymbols; 134import org.apache.tapestry5.internal.PropertyOverridesImpl; 135import org.apache.tapestry5.internal.TapestryInternalUtils; 136import org.apache.tapestry5.internal.ZeroNullFieldStrategy; 137import org.apache.tapestry5.internal.alerts.AlertManagerImpl; 138import org.apache.tapestry5.internal.beaneditor.EnvironmentMessages; 139import org.apache.tapestry5.internal.beaneditor.MessagesConstraintGenerator; 140import org.apache.tapestry5.internal.beaneditor.PrimitiveFieldConstraintGenerator; 141import org.apache.tapestry5.internal.beaneditor.ValidateAnnotationConstraintGenerator; 142import org.apache.tapestry5.internal.bindings.AssetBindingFactory; 143import org.apache.tapestry5.internal.bindings.BlockBindingFactory; 144import org.apache.tapestry5.internal.bindings.ComponentBindingFactory; 145import org.apache.tapestry5.internal.bindings.ContextBindingFactory; 146import org.apache.tapestry5.internal.bindings.LiteralBindingFactory; 147import org.apache.tapestry5.internal.bindings.MessageBindingFactory; 148import org.apache.tapestry5.internal.bindings.NullFieldStrategyBindingFactory; 149import org.apache.tapestry5.internal.bindings.PropBindingFactory; 150import org.apache.tapestry5.internal.bindings.RenderVariableBindingFactory; 151import org.apache.tapestry5.internal.bindings.SymbolBindingFactory; 152import org.apache.tapestry5.internal.bindings.TranslateBindingFactory; 153import org.apache.tapestry5.internal.bindings.ValidateBindingFactory; 154import org.apache.tapestry5.internal.dynamic.DynamicTemplateParserImpl; 155import org.apache.tapestry5.internal.grid.CollectionGridDataSource; 156import org.apache.tapestry5.internal.grid.NullDataSource; 157import org.apache.tapestry5.internal.renderers.AvailableValuesRenderer; 158import org.apache.tapestry5.internal.renderers.ComponentResourcesRenderer; 159import org.apache.tapestry5.internal.renderers.EventContextRenderer; 160import org.apache.tapestry5.internal.renderers.ListRenderer; 161import org.apache.tapestry5.internal.renderers.LocationRenderer; 162import org.apache.tapestry5.internal.renderers.ObjectArrayRenderer; 163import org.apache.tapestry5.internal.renderers.RequestRenderer; 164import org.apache.tapestry5.internal.services.*; 165import org.apache.tapestry5.internal.services.ajax.AjaxFormUpdateFilter; 166import org.apache.tapestry5.internal.services.ajax.AjaxResponseRendererImpl; 167import org.apache.tapestry5.internal.services.ajax.MultiZoneUpdateEventResultProcessor; 168import org.apache.tapestry5.internal.services.exceptions.ExceptionReportWriterImpl; 169import org.apache.tapestry5.internal.services.exceptions.ExceptionReporterImpl; 170import org.apache.tapestry5.internal.services.linktransform.LinkTransformerImpl; 171import org.apache.tapestry5.internal.services.linktransform.LinkTransformerInterceptor; 172import org.apache.tapestry5.internal.services.messages.PropertiesFileParserImpl; 173import org.apache.tapestry5.internal.services.meta.ContentTypeExtractor; 174import org.apache.tapestry5.internal.services.meta.MetaAnnotationExtractor; 175import org.apache.tapestry5.internal.services.meta.MetaWorkerImpl; 176import org.apache.tapestry5.internal.services.meta.UnknownActivationContextExtractor; 177import org.apache.tapestry5.internal.services.rest.DefaultOpenApiDescriptionGenerator; 178import org.apache.tapestry5.internal.services.rest.DefaultOpenApiTypeDescriber; 179import org.apache.tapestry5.internal.services.rest.MappedEntityManagerImpl; 180import org.apache.tapestry5.internal.services.security.ClientWhitelistImpl; 181import org.apache.tapestry5.internal.services.security.LocalhostOnly; 182import org.apache.tapestry5.internal.services.templates.DefaultTemplateLocator; 183import org.apache.tapestry5.internal.services.templates.PageTemplateLocator; 184import org.apache.tapestry5.internal.transform.ActivationRequestParameterWorker; 185import org.apache.tapestry5.internal.transform.ApplicationStateWorker; 186import org.apache.tapestry5.internal.transform.BindParameterWorker; 187import org.apache.tapestry5.internal.transform.CachedWorker; 188import org.apache.tapestry5.internal.transform.ComponentWorker; 189import org.apache.tapestry5.internal.transform.DiscardAfterWorker; 190import org.apache.tapestry5.internal.transform.EnvironmentalWorker; 191import org.apache.tapestry5.internal.transform.HeartbeatDeferredWorker; 192import org.apache.tapestry5.internal.transform.ImportWorker; 193import org.apache.tapestry5.internal.transform.InjectComponentWorker; 194import org.apache.tapestry5.internal.transform.InjectContainerWorker; 195import org.apache.tapestry5.internal.transform.InjectNamedProvider; 196import org.apache.tapestry5.internal.transform.InjectPageWorker; 197import org.apache.tapestry5.internal.transform.InjectServiceWorker; 198import org.apache.tapestry5.internal.transform.InjectWorker; 199import org.apache.tapestry5.internal.transform.LogWorker; 200import org.apache.tapestry5.internal.transform.MixinAfterWorker; 201import org.apache.tapestry5.internal.transform.MixinWorker; 202import org.apache.tapestry5.internal.transform.OnEventWorker; 203import org.apache.tapestry5.internal.transform.OperationWorker; 204import org.apache.tapestry5.internal.transform.PageActivationContextWorker; 205import org.apache.tapestry5.internal.transform.PageLifecycleAnnotationWorker; 206import org.apache.tapestry5.internal.transform.PageResetAnnotationWorker; 207import org.apache.tapestry5.internal.transform.ParameterWorker; 208import org.apache.tapestry5.internal.transform.PersistWorker; 209import org.apache.tapestry5.internal.transform.PropertyWorker; 210import org.apache.tapestry5.internal.transform.RenderCommandWorker; 211import org.apache.tapestry5.internal.transform.RenderPhaseMethodWorker; 212import org.apache.tapestry5.internal.transform.RetainWorker; 213import org.apache.tapestry5.internal.transform.SessionAttributeWorker; 214import org.apache.tapestry5.internal.transform.SupportsInformalParametersWorker; 215import org.apache.tapestry5.internal.transform.UnclaimedFieldWorker; 216import org.apache.tapestry5.internal.translator.NumericTranslator; 217import org.apache.tapestry5.internal.translator.NumericTranslatorSupport; 218import org.apache.tapestry5.internal.translator.StringTranslator; 219import org.apache.tapestry5.internal.util.RenderableAsBlock; 220import org.apache.tapestry5.internal.util.StringRenderable; 221import org.apache.tapestry5.internal.validator.ValidatorMacroImpl; 222import org.apache.tapestry5.ioc.MethodAdviceReceiver; 223import org.apache.tapestry5.ioc.OperationTracker; 224import org.apache.tapestry5.ioc.ScopeConstants; 225import org.apache.tapestry5.ioc.ServiceBinder; 226import org.apache.tapestry5.ioc.annotations.Advise; 227import org.apache.tapestry5.ioc.annotations.Autobuild; 228import org.apache.tapestry5.ioc.annotations.ComponentClasses; 229import org.apache.tapestry5.ioc.annotations.ComponentLayer; 230import org.apache.tapestry5.ioc.annotations.Contribute; 231import org.apache.tapestry5.ioc.annotations.ImportModule; 232import org.apache.tapestry5.ioc.annotations.Inject; 233import org.apache.tapestry5.ioc.annotations.InjectService; 234import org.apache.tapestry5.ioc.annotations.Local; 235import org.apache.tapestry5.ioc.annotations.Marker; 236import org.apache.tapestry5.ioc.annotations.Match; 237import org.apache.tapestry5.ioc.annotations.Operation; 238import org.apache.tapestry5.ioc.annotations.Primary; 239import org.apache.tapestry5.ioc.annotations.Scope; 240import org.apache.tapestry5.ioc.annotations.Startup; 241import org.apache.tapestry5.ioc.annotations.Symbol; 242import org.apache.tapestry5.ioc.services.Builtin; 243import org.apache.tapestry5.ioc.services.ChainBuilder; 244import org.apache.tapestry5.ioc.services.LazyAdvisor; 245import org.apache.tapestry5.ioc.services.MasterObjectProvider; 246import org.apache.tapestry5.ioc.services.PerThreadValue; 247import org.apache.tapestry5.ioc.services.PerthreadManager; 248import org.apache.tapestry5.ioc.services.PipelineBuilder; 249import org.apache.tapestry5.ioc.services.PropertyShadowBuilder; 250import org.apache.tapestry5.ioc.services.ServiceOverride; 251import org.apache.tapestry5.ioc.services.StrategyBuilder; 252import org.apache.tapestry5.ioc.services.SymbolSource; 253import org.apache.tapestry5.ioc.services.ThreadLocale; 254import org.apache.tapestry5.ioc.services.UpdateListener; 255import org.apache.tapestry5.ioc.services.UpdateListenerHub; 256import org.apache.tapestry5.json.JSONArray; 257import org.apache.tapestry5.json.JSONObject; 258import org.apache.tapestry5.json.modules.JSONModule; 259import org.apache.tapestry5.plastic.MethodAdvice; 260import org.apache.tapestry5.plastic.MethodDescription; 261import org.apache.tapestry5.plastic.MethodInvocation; 262import org.apache.tapestry5.runtime.Component; 263import org.apache.tapestry5.runtime.ComponentResourcesAware; 264import org.apache.tapestry5.runtime.RenderCommand; 265import org.apache.tapestry5.runtime.RenderQueue; 266import org.apache.tapestry5.services.Ajax; 267import org.apache.tapestry5.services.ApplicationStateManager; 268import org.apache.tapestry5.services.ApplicationStatePersistenceStrategy; 269import org.apache.tapestry5.services.ApplicationStatePersistenceStrategySource; 270import org.apache.tapestry5.services.AssetFactory; 271import org.apache.tapestry5.services.AssetSource; 272import org.apache.tapestry5.services.BeanBlockContribution; 273import org.apache.tapestry5.services.BeanBlockOverrideSource; 274import org.apache.tapestry5.services.BeanBlockSource; 275import org.apache.tapestry5.services.BindingFactory; 276import org.apache.tapestry5.services.BindingSource; 277import org.apache.tapestry5.services.ClientBehaviorSupport; 278import org.apache.tapestry5.services.ClientDataEncoder; 279import org.apache.tapestry5.services.ComponentClassResolver; 280import org.apache.tapestry5.services.ComponentDefaultProvider; 281import org.apache.tapestry5.services.ComponentEventLinkEncoder; 282import org.apache.tapestry5.services.ComponentEventRequestFilter; 283import org.apache.tapestry5.services.ComponentEventRequestHandler; 284import org.apache.tapestry5.services.ComponentEventRequestParameters; 285import org.apache.tapestry5.services.ComponentEventResultProcessor; 286import org.apache.tapestry5.services.ComponentLibraryInfo; 287import org.apache.tapestry5.services.ComponentLibraryInfoSource; 288import org.apache.tapestry5.services.ComponentMessages; 289import org.apache.tapestry5.services.ComponentOverride; 290import org.apache.tapestry5.services.ComponentRequestFilter; 291import org.apache.tapestry5.services.ComponentRequestHandler; 292import org.apache.tapestry5.services.ComponentSource; 293import org.apache.tapestry5.services.ComponentTemplates; 294import org.apache.tapestry5.services.ContextPathEncoder; 295import org.apache.tapestry5.services.ContextProvider; 296import org.apache.tapestry5.services.ContextValueEncoder; 297import org.apache.tapestry5.services.Cookies; 298import org.apache.tapestry5.services.Core; 299import org.apache.tapestry5.services.DateUtilities; 300import org.apache.tapestry5.services.DefaultObjectRenderer; 301import org.apache.tapestry5.services.DisplayBlockContribution; 302import org.apache.tapestry5.services.EditBlockContribution; 303import org.apache.tapestry5.services.Environment; 304import org.apache.tapestry5.services.EnvironmentalShadowBuilder; 305import org.apache.tapestry5.services.ExceptionReportWriter; 306import org.apache.tapestry5.services.ExceptionReporter; 307import org.apache.tapestry5.services.FieldTranslatorSource; 308import org.apache.tapestry5.services.FieldValidatorDefaultSource; 309import org.apache.tapestry5.services.FieldValidatorSource; 310import org.apache.tapestry5.services.FormSupport; 311import org.apache.tapestry5.services.Heartbeat; 312import org.apache.tapestry5.services.HiddenFieldLocationRules; 313import org.apache.tapestry5.services.Html5Support; 314import org.apache.tapestry5.services.HttpError; 315import org.apache.tapestry5.services.HttpStatus; 316import org.apache.tapestry5.services.InitializeActivePageName; 317import org.apache.tapestry5.services.LibraryMapping; 318import org.apache.tapestry5.services.LinkCreationHub; 319import org.apache.tapestry5.services.MarkupRenderer; 320import org.apache.tapestry5.services.MarkupRendererFilter; 321import org.apache.tapestry5.services.MarkupWriterFactory; 322import org.apache.tapestry5.services.MetaDataLocator; 323import org.apache.tapestry5.services.NullFieldStrategySource; 324import org.apache.tapestry5.services.ObjectRenderer; 325import org.apache.tapestry5.services.PageDocumentGenerator; 326import org.apache.tapestry5.services.PageRenderLinkSource; 327import org.apache.tapestry5.services.PageRenderRequestFilter; 328import org.apache.tapestry5.services.PageRenderRequestHandler; 329import org.apache.tapestry5.services.PageRenderRequestParameters; 330import org.apache.tapestry5.services.PartialMarkupRenderer; 331import org.apache.tapestry5.services.PartialMarkupRendererFilter; 332import org.apache.tapestry5.services.PartialTemplateRenderer; 333import org.apache.tapestry5.services.PathConstructor; 334import org.apache.tapestry5.services.PersistentFieldStrategy; 335import org.apache.tapestry5.services.PersistentLocale; 336import org.apache.tapestry5.services.RelativeElementPosition; 337import org.apache.tapestry5.services.RequestExceptionHandler; 338import org.apache.tapestry5.services.ResourceDigestGenerator; 339import org.apache.tapestry5.services.ResponseRenderer; 340import org.apache.tapestry5.services.SelectModelFactory; 341import org.apache.tapestry5.services.StackTraceElementAnalyzer; 342import org.apache.tapestry5.services.StackTraceElementClassConstants; 343import org.apache.tapestry5.services.StreamPageContent; 344import org.apache.tapestry5.services.Traditional; 345import org.apache.tapestry5.services.TransformConstants; 346import org.apache.tapestry5.services.TranslatorAlternatesSource; 347import org.apache.tapestry5.services.TranslatorSource; 348import org.apache.tapestry5.services.URLEncoder; 349import org.apache.tapestry5.services.ValidationConstraintGenerator; 350import org.apache.tapestry5.services.ValidationDecoratorFactory; 351import org.apache.tapestry5.services.ValueEncoderFactory; 352import org.apache.tapestry5.services.ValueEncoderSource; 353import org.apache.tapestry5.services.ValueLabelProvider; 354import org.apache.tapestry5.services.ajax.AjaxResponseRenderer; 355import org.apache.tapestry5.services.dynamic.DynamicTemplate; 356import org.apache.tapestry5.services.dynamic.DynamicTemplateParser; 357import org.apache.tapestry5.services.javascript.JavaScriptSupport; 358import org.apache.tapestry5.services.javascript.ModuleManager; 359import org.apache.tapestry5.services.linktransform.ComponentEventLinkTransformer; 360import org.apache.tapestry5.services.linktransform.LinkTransformer; 361import org.apache.tapestry5.services.linktransform.PageRenderLinkTransformer; 362import org.apache.tapestry5.services.messages.ComponentMessagesSource; 363import org.apache.tapestry5.services.messages.PropertiesFileParser; 364import org.apache.tapestry5.services.meta.FixedExtractor; 365import org.apache.tapestry5.services.meta.MetaDataExtractor; 366import org.apache.tapestry5.services.meta.MetaWorker; 367import org.apache.tapestry5.services.pageload.PreloaderMode; 368import org.apache.tapestry5.services.rest.OpenApiDescriptionGenerator; 369import org.apache.tapestry5.services.rest.OpenApiTypeDescriber; 370import org.apache.tapestry5.services.rest.MappedEntityManager; 371import org.apache.tapestry5.services.security.ClientWhitelist; 372import org.apache.tapestry5.services.security.WhitelistAnalyzer; 373import org.apache.tapestry5.services.templates.ComponentTemplateLocator; 374import org.apache.tapestry5.services.transform.ComponentClassTransformWorker2; 375import org.apache.tapestry5.services.transform.InjectionProvider2; 376import org.apache.tapestry5.validator.Checked; 377import org.apache.tapestry5.validator.Email; 378import org.apache.tapestry5.validator.Max; 379import org.apache.tapestry5.validator.MaxLength; 380import org.apache.tapestry5.validator.Min; 381import org.apache.tapestry5.validator.MinLength; 382import org.apache.tapestry5.validator.None; 383import org.apache.tapestry5.validator.Regexp; 384import org.apache.tapestry5.validator.Required; 385import org.apache.tapestry5.validator.Unchecked; 386import org.apache.tapestry5.validator.ValidatorMacro; 387import org.slf4j.Logger; 388 389/** 390 * The root module for Tapestry. 391 */ 392@Marker(Core.class) 393@ImportModule( 394 {InternalModule.class, AssetsModule.class, PageLoadModule.class, JavaScriptModule.class, CompatibilityModule.class, DashboardModule.class, TapestryHttpModule.class, JSONModule.class}) 395public final class TapestryModule 396{ 397 private final PipelineBuilder pipelineBuilder; 398 399 private final PropertyShadowBuilder shadowBuilder; 400 401 private final Environment environment; 402 403 private final StrategyBuilder strategyBuilder; 404 405 private final PropertyAccess propertyAccess; 406 407 private final ChainBuilder chainBuilder; 408 409 private final Request request; 410 411 private final Response response; 412 413 private final RequestGlobals requestGlobals; 414 415 private final EnvironmentalShadowBuilder environmentalBuilder; 416 417 private final EndOfRequestEventHub endOfRequestEventHub; 418 419 /** 420 * We inject all sorts of common dependencies (including builders) into the 421 * module itself (note: even though some of 422 * these service are defined by the module itself, that's ok because 423 * services are always lazy proxies). This isn't 424 * about efficiency (it may be slightly more efficient, but not in any 425 * noticeable way), it's about eliminating the 426 * need to keep injecting these dependencies into individual service builder 427 * and contribution methods. 428 */ 429 public TapestryModule(PipelineBuilder pipelineBuilder, 430 431 PropertyShadowBuilder shadowBuilder, 432 433 RequestGlobals requestGlobals, 434 435 ChainBuilder chainBuilder, 436 437 Environment environment, 438 439 StrategyBuilder strategyBuilder, 440 441 PropertyAccess propertyAccess, 442 443 Request request, 444 445 Response response, 446 447 EnvironmentalShadowBuilder environmentalBuilder, 448 449 EndOfRequestEventHub endOfRequestEventHub) 450 { 451 this.pipelineBuilder = pipelineBuilder; 452 this.shadowBuilder = shadowBuilder; 453 this.requestGlobals = requestGlobals; 454 this.chainBuilder = chainBuilder; 455 this.environment = environment; 456 this.strategyBuilder = strategyBuilder; 457 this.propertyAccess = propertyAccess; 458 this.request = request; 459 this.response = response; 460 this.environmentalBuilder = environmentalBuilder; 461 this.endOfRequestEventHub = endOfRequestEventHub; 462 } 463 464 public static void bind(ServiceBinder binder) 465 { 466 binder.bind(PersistentLocale.class, PersistentLocaleImpl.class); 467 binder.bind(ApplicationStateManager.class, ApplicationStateManagerImpl.class); 468 binder.bind(ApplicationStatePersistenceStrategySource.class, 469 ApplicationStatePersistenceStrategySourceImpl.class); 470 binder.bind(BindingSource.class, BindingSourceImpl.class); 471 binder.bind(FieldValidatorSource.class, FieldValidatorSourceImpl.class); 472 binder.bind(Cookies.class, CookiesImpl.class); 473 binder.bind(FieldValidatorDefaultSource.class, FieldValidatorDefaultSourceImpl.class); 474 binder.bind(ResourceDigestGenerator.class, ResourceDigestGeneratorImpl.class); // Remove in 5.5 475 binder.bind(ValidationConstraintGenerator.class, ValidationConstraintGeneratorImpl.class); 476 binder.bind(EnvironmentalShadowBuilder.class, EnvironmentalShadowBuilderImpl.class); 477 binder.bind(ComponentSource.class, ComponentSourceImpl.class); 478 binder.bind(BeanModelSource.class, BeanModelSourceImpl.class); 479 binder.bind(BeanBlockSource.class, BeanBlockSourceImpl.class); 480 binder.bind(ComponentDefaultProvider.class, ComponentDefaultProviderImpl.class); 481 binder.bind(MarkupWriterFactory.class, MarkupWriterFactoryImpl.class); 482 binder.bind(FieldValidationSupport.class, FieldValidationSupportImpl.class); 483 binder.bind(ObjectRenderer.class, LocationRenderer.class).withSimpleId(); 484 binder.bind(ObjectProvider.class, AssetObjectProvider.class).withSimpleId(); 485 binder.bind(RequestExceptionHandler.class, DefaultRequestExceptionHandler.class); 486 binder.bind(ComponentEventResultProcessor.class, ComponentInstanceResultProcessor.class).withSimpleId(); 487 binder.bind(NullFieldStrategySource.class, NullFieldStrategySourceImpl.class); 488 binder.bind(HttpServletRequestFilter.class, IgnoredPathsFilter.class).withSimpleId(); 489 binder.bind(ContextValueEncoder.class, ContextValueEncoderImpl.class); 490 binder.bind(BeanBlockOverrideSource.class, BeanBlockOverrideSourceImpl.class); 491 binder.bind(HiddenFieldLocationRules.class, HiddenFieldLocationRulesImpl.class); 492 binder.bind(PageDocumentGenerator.class, PageDocumentGeneratorImpl.class); 493 binder.bind(ResponseRenderer.class, ResponseRendererImpl.class); 494 binder.bind(FieldTranslatorSource.class, FieldTranslatorSourceImpl.class); 495 binder.bind(BindingFactory.class, MessageBindingFactory.class).withSimpleId(); 496 binder.bind(BindingFactory.class, ValidateBindingFactory.class).withSimpleId(); 497 binder.bind(BindingFactory.class, TranslateBindingFactory.class).withSimpleId(); 498 binder.bind(BindingFactory.class, AssetBindingFactory.class).withSimpleId(); 499 binder.bind(BindingFactory.class, ContextBindingFactory.class).withSimpleId(); 500 binder.bind(BindingFactory.class, NullFieldStrategyBindingFactory.class).withSimpleId(); 501 binder.bind(BindingFactory.class, SymbolBindingFactory.class).withSimpleId(); 502 binder.bind(URLEncoder.class, URLEncoderImpl.class); 503 binder.bind(ContextPathEncoder.class, ContextPathEncoderImpl.class); 504 binder.bind(ApplicationStatePersistenceStrategy.class, SessionApplicationStatePersistenceStrategy.class).withSimpleId(); 505 binder.bind(NumericTranslatorSupport.class); 506 binder.bind(ClientDataEncoder.class, ClientDataEncoderImpl.class); 507 binder.bind(ComponentEventLinkEncoder.class, ComponentEventLinkEncoderImpl.class); 508 binder.bind(PageRenderLinkSource.class, PageRenderLinkSourceImpl.class); 509 binder.bind(ValidatorMacro.class, ValidatorMacroImpl.class); 510 binder.bind(PropertiesFileParser.class, PropertiesFileParserImpl.class); 511 binder.bind(PageActivator.class, PageActivatorImpl.class); 512 binder.bind(Dispatcher.class, AssetDispatcher.class).withSimpleId(); 513 binder.bind(TranslatorAlternatesSource.class, TranslatorAlternatesSourceImpl.class); 514 binder.bind(MetaWorker.class, MetaWorkerImpl.class); 515 binder.bind(LinkTransformer.class, LinkTransformerImpl.class); 516 binder.bind(SelectModelFactory.class, SelectModelFactoryImpl.class); 517 binder.bind(DynamicTemplateParser.class, DynamicTemplateParserImpl.class); 518 binder.bind(AjaxResponseRenderer.class, AjaxResponseRendererImpl.class); 519 binder.bind(AlertManager.class, AlertManagerImpl.class); 520 binder.bind(ValidationDecoratorFactory.class, ValidationDecoratorFactoryImpl.class); 521 binder.bind(PropertyConduitSource.class, PropertyConduitSourceImpl.class); 522 binder.bind(ClientWhitelist.class, ClientWhitelistImpl.class); 523 binder.bind(MetaDataLocator.class, MetaDataLocatorImpl.class); 524 binder.bind(ComponentClassCache.class, ComponentClassCacheImpl.class); 525 binder.bind(PageActivationContextCollector.class, PageActivationContextCollectorImpl.class); 526 binder.bind(StringInterner.class, StringInternerImpl.class); 527 binder.bind(ValueEncoderSource.class, ValueEncoderSourceImpl.class); 528 binder.bind(PathConstructor.class, PathConstructorImpl.class); 529 binder.bind(DateUtilities.class, DateUtilitiesImpl.class); 530 binder.bind(PartialTemplateRenderer.class, PartialTemplateRendererImpl.class); 531 binder.bind(ExceptionReporter.class, ExceptionReporterImpl.class); 532 binder.bind(ExceptionReportWriter.class, ExceptionReportWriterImpl.class); 533 binder.bind(ComponentOverride.class, ComponentOverrideImpl.class).eagerLoad(); 534 binder.bind(Html5Support.class, Html5SupportImpl.class); 535 binder.bind(MappedEntityManager.class, MappedEntityManagerImpl.class); 536 } 537 538 // ======================================================================== 539 // 540 // Service Builder Methods (static) 541 // 542 // ======================================================================== 543 544 // ======================================================================== 545 // 546 // Service Contribution Methods (static) 547 // 548 // ======================================================================== 549 550 /** 551 * Contributes the factory for several built-in binding prefixes ("asset", 552 * "block", "component", "literal", prop", 553 * "nullfieldstrategy", "message", "validate", "translate", "var"). 554 */ 555 public static void contributeBindingSource(MappedConfiguration<String, BindingFactory> configuration, 556 557 @InjectService("PropBindingFactory") 558 BindingFactory propBindingFactory, 559 560 @InjectService("MessageBindingFactory") 561 BindingFactory messageBindingFactory, 562 563 @InjectService("ValidateBindingFactory") 564 BindingFactory validateBindingFactory, 565 566 @InjectService("TranslateBindingFactory") 567 BindingFactory translateBindingFactory, 568 569 @InjectService("AssetBindingFactory") 570 BindingFactory assetBindingFactory, 571 572 @InjectService("NullFieldStrategyBindingFactory") 573 BindingFactory nullFieldStrategyBindingFactory, 574 575 @InjectService("ContextBindingFactory") 576 BindingFactory contextBindingFactory, 577 578 @InjectService("SymbolBindingFactory") 579 BindingFactory symbolBindingFactory) 580 { 581 configuration.add(BindingConstants.LITERAL, new LiteralBindingFactory()); 582 configuration.add(BindingConstants.COMPONENT, new ComponentBindingFactory()); 583 configuration.add(BindingConstants.VAR, new RenderVariableBindingFactory()); 584 configuration.add(BindingConstants.BLOCK, new BlockBindingFactory()); 585 586 configuration.add(BindingConstants.PROP, propBindingFactory); 587 configuration.add(BindingConstants.MESSAGE, messageBindingFactory); 588 configuration.add(BindingConstants.VALIDATE, validateBindingFactory); 589 configuration.add(BindingConstants.TRANSLATE, translateBindingFactory); 590 configuration.add(BindingConstants.ASSET, assetBindingFactory); 591 configuration.add(BindingConstants.NULLFIELDSTRATEGY, nullFieldStrategyBindingFactory); 592 configuration.add(BindingConstants.CONTEXT, contextBindingFactory); 593 configuration.add(BindingConstants.SYMBOL, symbolBindingFactory); 594 } 595 596 597 @Contribute(ComponentClassResolver.class) 598 public static void provideCoreAndAppLibraries(Configuration<LibraryMapping> configuration, 599 @Symbol(TapestryHttpInternalConstants.TAPESTRY_APP_PACKAGE_PARAM) 600 String appRootPackage) 601 { 602 configuration.add(new LibraryMapping(InternalConstants.CORE_LIBRARY, "org.apache.tapestry5.corelib")); 603 configuration.add(new LibraryMapping("", appRootPackage)); 604 } 605 606 /** 607 * Adds a number of standard component class transform workers: 608 * <dl> 609 * <dt>Parameter</dt> 610 * <dd>Identifies parameters based on the {@link org.apache.tapestry5.annotations.Parameter} annotation</dd> 611 * <dt>BindParameter</dt> 612 * <dd>Support for the {@link BindParameter} annotation</dd> 613 * <dt>Property</dt> 614 * <dd>Generates accessor methods if {@link org.apache.tapestry5.annotations.Property} annotation is present</dd> 615 * <dt>Import</dt> 616 * <dd>Supports the {@link Import} annotation</dd> 617 * <dt>UnclaimedField</dt> 618 * <dd>Manages unclaimed fields, storing their value in a {@link PerThreadValue}</dd> 619 * <dt>OnEvent</dt> 620 * <dd>Handle the @OnEvent annotation, and related naming convention</dd> 621 * <dt>RenderCommand</dt> 622 * <dd>Ensures all components also implement {@link org.apache.tapestry5.runtime.RenderCommand}</dd> 623 * <dt>SupportsInformalParameters</dt> 624 * <dd>Checks for the annotation</dd> 625 * <dt>RenderPhase</dt> 626 * <dd>Link in render phase methods</dd> 627 * <dt>Retain</dt> 628 * <dd>Allows fields to retain their values between requests</dd> 629 * <dt>Meta</dt> 630 * <dd>Checks for meta data annotations and adds it to the component model</dd> 631 * <dt>PageActivationContext</dt> <dd>Support for {@link PageActivationContext} annotation</dd> 632 * <dt>DiscardAfter</dt> <dd>Support for {@link DiscardAfter} method annotation </dd> 633 * <dt>MixinAfter</dt> <dd>Support for the {@link MixinAfter} mixin class annotation</dd> 634 * <dt>PageReset</dt> 635 * <dd>Checks for the {@link PageReset} annotation</dd> 636 * <dt>Mixin</dt> 637 * <dd>Adds a mixin as part of a component's implementation</dd> 638 * <dt>Cached</dt> 639 * <dd>Checks for the {@link org.apache.tapestry5.annotations.Cached} annotation</dd> 640 * <dt>ActivationRequestParameter</dt> 641 * <dd>Support for the {@link ActivationRequestParameter} annotation</dd> 642 * <dt>PageLoaded, PageAttached, PageDetached</dt> 643 * <dd>Support for annotations {@link PageLoaded}, {@link PageAttached}, {@link PageDetached}</dd> 644 * <dt>InjectService</dt> 645 * <dd>Handles the {@link org.apache.tapestry5.ioc.annotations.InjectService} annotation</dd> 646 * <dt>Component</dt> 647 * <dd>Defines embedded components based on the {@link org.apache.tapestry5.annotations.Component} annotation</dd> 648 * <dt>Environment</dt> 649 * <dd>Allows fields to contain values extracted from the {@link org.apache.tapestry5.services.Environment} service</dd> 650 * <dt>ApplicationState</dt> 651 * <dd>Converts fields that reference application state objects</dd> 652 * <dt>Persist</dt> 653 * <dd>Allows fields to store their their value persistently between requests via {@link Persist}</dd> 654 * <dt>SessionAttribute</dt> 655 * <dd>Support for the {@link SessionAttribute}</dd> 656 * <dt>Log</dt> 657 * <dd>Checks for the {@link org.apache.tapestry5.annotations.Log} annotation</dd> 658 * <dt>HeartbeatDeferred 659 * <dd>Support for the {@link HeartbeatDeferred} annotation, which defers method invocation to the end of the {@link Heartbeat} 660 * <dt>Inject</dt> 661 * <dd>Used with the {@link org.apache.tapestry5.ioc.annotations.Inject} annotation, when a value is supplied</dd> 662 * <dt>Operation</dt> <dd>Support for the {@link Operation} method annotation</dd> 663 * </dl> 664 */ 665 @Contribute(ComponentClassTransformWorker2.class) 666 @Primary 667 public static void provideTransformWorkers( 668 OrderedConfiguration<ComponentClassTransformWorker2> configuration, 669 MetaWorker metaWorker, 670 ComponentClassResolver resolver) 671 { 672 configuration.add("Property", new PropertyWorker()); 673 674 // Order this one pretty early: 675 676 configuration.addInstance("Operation", OperationWorker.class); 677 678 configuration.add("RenderCommand", new RenderCommandWorker()); 679 680 configuration.addInstance("OnEvent", OnEventWorker.class); 681 682 configuration.add("MixinAfter", new MixinAfterWorker()); 683 684 // These must come after Property, since they actually delete fields 685 // that may still have the annotation 686 configuration.addInstance("ApplicationState", ApplicationStateWorker.class); 687 configuration.addInstance("Environment", EnvironmentalWorker.class); 688 689 configuration.add("Component", new ComponentWorker(resolver)); 690 configuration.add("Mixin", new MixinWorker(resolver)); 691 configuration.addInstance("InjectPage", InjectPageWorker.class); 692 configuration.addInstance("InjectComponent", InjectComponentWorker.class); 693 configuration.addInstance("InjectContainer", InjectContainerWorker.class); 694 695 // Default values for parameters are often some form of injection, so 696 // make sure that Parameter fields are processed after injections. 697 698 configuration.addInstance("Parameter", ParameterWorker.class); 699 700 // bind parameter should always go after parameter to make sure all 701 // parameters have been properly setup. 702 configuration.addInstance("BindParameter", BindParameterWorker.class); 703 704 configuration.add("SupportsInformalParameters", new SupportsInformalParametersWorker()); 705 706 configuration.addInstance("RenderPhase", RenderPhaseMethodWorker.class); 707 708 // Import advises methods, usually render phase methods, so it must come after RenderPhase. 709 710 configuration.addInstance("Import", ImportWorker.class); 711 712 configuration.add("Meta", metaWorker.getWorker()); 713 714 configuration.add("Retain", new RetainWorker()); 715 716 configuration.add("PageActivationContext", new PageActivationContextWorker()); 717 configuration 718 .addInstance("ActivationRequestParameter", ActivationRequestParameterWorker.class); 719 720 configuration.addInstance("Cached", CachedWorker.class); 721 722 configuration.addInstance("DiscardAfter", DiscardAfterWorker.class); 723 724 add(configuration, PageLoaded.class, TransformConstants.CONTAINING_PAGE_DID_LOAD_DESCRIPTION); 725 add(configuration, PageAttached.class, TransformConstants.CONTAINING_PAGE_DID_ATTACH_DESCRIPTION); 726 add(configuration, PageDetached.class, TransformConstants.CONTAINING_PAGE_DID_DETACH_DESCRIPTION); 727 728 configuration.addInstance("PageReset", PageResetAnnotationWorker.class); 729 configuration.addInstance("InjectService", InjectServiceWorker.class); 730 731 configuration.addInstance("Inject", InjectWorker.class); 732 733 configuration.addInstance("Persist", PersistWorker.class); 734 735 configuration.addInstance("SessionAttribute", SessionAttributeWorker.class); 736 737 configuration.addInstance("Log", LogWorker.class); 738 739 configuration.addInstance("HeartbeatDeferred", HeartbeatDeferredWorker.class); 740 741 // This one is always last. Any additional private fields that aren't 742 // annotated will 743 // be converted to clear out at the end of the request. 744 745 configuration.addInstance("UnclaimedField", UnclaimedFieldWorker.class, "after:*"); 746 } 747 748 /** 749 * <dl> 750 * <dt>Annotation</dt> 751 * <dd>Checks for {@link org.apache.tapestry5.beaneditor.DataType} annotation</dd> 752 * <dt>Default (ordered last)</dt> 753 * <dd> 754 * {@link org.apache.tapestry5.commons.internal.services.DefaultDataTypeAnalyzer} service ( 755 * {@link #contributeDefaultDataTypeAnalyzer(org.apache.tapestry5.commons.MappedConfiguration)} )</dd> 756 * </dl> 757 */ 758 public static void contributeDataTypeAnalyzer(OrderedConfiguration<DataTypeAnalyzer> configuration, 759 @InjectService("DefaultDataTypeAnalyzer") 760 DataTypeAnalyzer defaultDataTypeAnalyzer) 761 { 762 configuration.add("Annotation", new AnnotationDataTypeAnalyzer()); 763 configuration.add("Default", defaultDataTypeAnalyzer, "after:*"); 764 } 765 766 /** 767 * Maps property types to data type names: 768 * <ul> 769 * <li>String --> text 770 * <li>Number --> number 771 * <li>Enum --> enum 772 * <li>Boolean --> boolean 773 * <li>Date --> date 774 * </ul> 775 */ 776 public static void contributeDefaultDataTypeAnalyzer(MappedConfiguration<Class, String> configuration) 777 { 778 BasicDataTypeAnalyzers.provideDefaultDataTypeAnalyzers(configuration); 779 } 780 781 @Contribute(BeanBlockSource.class) 782 public static void provideDefaultBeanBlocks(Configuration<BeanBlockContribution> configuration) 783 { 784 addEditBlock(configuration, DataTypeConstants.TEXT); 785 addEditBlock(configuration, DataTypeConstants.NUMBER); 786 addEditBlock(configuration, DataTypeConstants.ENUM); 787 addEditBlock(configuration, DataTypeConstants.BOOLEAN); 788 addEditBlock(configuration, DataTypeConstants.DATE); 789 addEditBlock(configuration, DataTypeConstants.PASSWORD); 790 addEditBlock(configuration, DataTypeConstants.CALENDAR); 791 792 // longtext uses a text area, not a text field 793 794 addEditBlock(configuration, DataTypeConstants.LONG_TEXT); 795 796 addDisplayBlock(configuration, DataTypeConstants.ENUM); 797 addDisplayBlock(configuration, DataTypeConstants.DATE); 798 addDisplayBlock(configuration, DataTypeConstants.CALENDAR); 799 800 // Password and long text have special output needs. 801 addDisplayBlock(configuration, DataTypeConstants.PASSWORD); 802 addDisplayBlock(configuration, DataTypeConstants.LONG_TEXT); 803 } 804 805 private static void addEditBlock(Configuration<BeanBlockContribution> configuration, String dataType) 806 { 807 addEditBlock(configuration, dataType, dataType); 808 } 809 810 private static void addEditBlock(Configuration<BeanBlockContribution> configuration, String dataType, String blockId) 811 { 812 configuration.add(new EditBlockContribution(dataType, "PropertyEditBlocks", blockId)); 813 } 814 815 private static void addDisplayBlock(Configuration<BeanBlockContribution> configuration, String dataType) 816 { 817 addDisplayBlock(configuration, dataType, dataType); 818 } 819 820 private static void addDisplayBlock(Configuration<BeanBlockContribution> configuration, String dataType, 821 String blockId) 822 { 823 configuration.add(new DisplayBlockContribution(dataType, "PropertyDisplayBlocks", blockId)); 824 } 825 826 /** 827 * Contributes the basic set of validators: 828 * <ul> 829 * <li>required</li> 830 * <li>minlength</li> 831 * <li>maxlength</li> 832 * <li>min</li> 833 * <li>max</li> 834 * <li>regexp</li> 835 * <li>email</li> 836 * <li>none</li> 837 * </ul> 838 */ 839 @Contribute(FieldValidatorSource.class) 840 public static void setupCoreFrameworkValidators(MappedConfiguration<String, Validator> configuration) 841 { 842 configuration.addInstance("required", Required.class); 843 configuration.addInstance("minlength", MinLength.class); 844 configuration.addInstance("maxlength", MaxLength.class); 845 configuration.addInstance("min", Min.class); 846 configuration.addInstance("max", Max.class); 847 configuration.addInstance("regexp", Regexp.class); 848 configuration.addInstance("email", Email.class); 849 configuration.addInstance("checked", Checked.class); 850 configuration.addInstance("unchecked", Unchecked.class); 851 configuration.add("none", new None()); 852 } 853 854 /** 855 * <dl> 856 * <dt>Default</dt> 857 * <dd>based on {@link MasterObjectProvider}</dd> 858 * <dt>Named</dt> <dd>Handles fields with the {@link javax.inject.Named} annotation</dd> 859 * <dt>Block</dt> 860 * <dd>injects fields of type {@link Block}</dd> 861 * <dt>CommonResources</dt> 862 * <dd>Access to properties of resources (log, messages, etc.)</dd> 863 * <dt>Asset</dt> 864 * <dd>injection of assets (triggered via {@link Path} annotation), with the path relative to the component class</dd> 865 * <dt>Service</dt> 866 * <dd>Ordered last, for use when Inject is present and nothing else works, matches field type against Tapestry IoC 867 * services</dd> 868 * </dl> 869 */ 870 @Contribute(InjectionProvider2.class) 871 public static void provideStandardInjectionProviders(OrderedConfiguration<InjectionProvider2> configuration, SymbolSource symbolSource, 872 873 AssetSource assetSource) 874 { 875 configuration.addInstance("Named", InjectNamedProvider.class); 876 configuration.add("Block", new BlockInjectionProvider()); 877 configuration.add("Asset", new AssetInjectionProvider(assetSource)); 878 879 configuration.add("CommonResources", new CommonResourcesInjectionProvider()); 880 881 configuration.addInstance("Default", DefaultInjectionProvider.class); 882 883 // This needs to be the last one, since it matches against services 884 // and might blow up if there is no match. 885 configuration.addInstance("Service", ServiceInjectionProvider.class, "after:*"); 886 } 887 888 /** 889 * Contributes two object providers: 890 * <dl> 891 * <dt>Asset 892 * <dt> 893 * <dd>Checks for the {@link Path} annotation, and injects an {@link Asset}</dd> 894 * <dt>Service</dt> 895 * <dd>Injects based on the {@link Service} annotation, if present</dd> 896 * <dt>ApplicationMessages</dt> 897 * <dd>Injects the global application messages</dd> 898 * </dl> 899 */ 900 public static void contributeMasterObjectProvider(OrderedConfiguration<ObjectProvider> configuration, 901 902 @InjectService("AssetObjectProvider") 903 ObjectProvider assetObjectProvider, 904 905 ObjectLocator locator) 906 { 907 configuration.add("Asset", assetObjectProvider, "before:AnnotationBasedContributions"); 908 909 configuration.add("Service", new ServiceAnnotationObjectProvider(), "before:AnnotationBasedContributions"); 910 911 configuration.add("ApplicationMessages", new ApplicationMessageCatalogObjectProvider(locator), 912 "before:AnnotationBasedContributions"); 913 914 } 915 916 /** 917 * <dl> 918 * <dt>StoreIntoGlobals</dt> 919 * <dd>Stores the request and response into {@link org.apache.tapestry5.http.services.RequestGlobals} at the start of the 920 * pipeline</dd> 921 * <dt>IgnoredPaths</dt> 922 * <dd>Identifies requests that are known (via the IgnoredPathsFilter service's configuration) to be mapped to other 923 * applications</dd> 924 * <dt>GZip</dt> 925 * <dd>Handles GZIP compression of response streams (if supported by client)</dd> 926 * </dl> 927 */ 928 public void contributeHttpServletRequestHandler(OrderedConfiguration<HttpServletRequestFilter> configuration, 929 930 @InjectService("IgnoredPathsFilter") 931 HttpServletRequestFilter ignoredPathsFilter) 932 { 933 configuration.add("IgnoredPaths", ignoredPathsFilter); 934 } 935 936 /** 937 * Continues a number of filters into the RequestHandler service: 938 * <dl> 939 * <dt>StaticFiles</dt> 940 * <dd>Checks to see if the request is for an actual file, if so, returns true to let the servlet container process 941 * the request</dd> 942 * <dt>CheckForUpdates</dt> 943 * <dd>Periodically fires events that checks to see if the file system sources for any cached data has changed (see 944 * {@link org.apache.tapestry5.internal.services.CheckForUpdatesFilter}). Starting in 5.3, this filter will be null 945 * in production mode (it will only be active in development mode). 946 * <dt>ErrorFilter</dt> 947 * <dd>Catches request errors and lets the {@link org.apache.tapestry5.services.RequestExceptionHandler} handle them 948 * </dd> 949 * <dt>StoreIntoGlobals</dt> 950 * <dd>Stores the request and response into the {@link org.apache.tapestry5.http.services.RequestGlobals} service (this 951 * is repeated at the end of the pipeline, in case any filter substitutes the request or response). 952 * <dt>EndOfRequest</dt> 953 * <dd>Notifies internal services that the request has ended</dd> 954 * </dl> 955 */ 956 public void contributeRequestHandler(OrderedConfiguration<RequestFilter> configuration, Context context, 957 958 @Symbol(TapestryHttpSymbolConstants.PRODUCTION_MODE) 959 boolean productionMode) 960 { 961 RequestFilter staticFilesFilter = new StaticFilesFilter(context); 962 963 RequestFilter storeIntoGlobals = new RequestFilter() 964 { 965 public boolean service(Request request, Response response, RequestHandler handler) throws IOException 966 { 967 requestGlobals.storeRequestResponse(request, response); 968 969 return handler.service(request, response); 970 } 971 }; 972 973 RequestFilter fireEndOfRequestEvent = new RequestFilter() 974 { 975 public boolean service(Request request, Response response, RequestHandler handler) throws IOException 976 { 977 try 978 { 979 return handler.service(request, response); 980 } finally 981 { 982 endOfRequestEventHub.fire(); 983 } 984 } 985 }; 986 987 if (productionMode) 988 { 989 configuration.add("CheckForUpdates", null, "before:*"); 990 } else 991 { 992 configuration.addInstance("CheckForUpdates", CheckForUpdatesFilter.class, "before:*"); 993 } 994 995 configuration.add("StaticFiles", staticFilesFilter); 996 997 configuration.add("StoreIntoGlobals", storeIntoGlobals); 998 999 configuration.add("EndOfRequest", fireEndOfRequestEvent); 1000 1001 configuration.addInstance("ErrorFilter", RequestErrorFilter.class); 1002 } 1003 1004 /** 1005 * Contributes the basic set of translators: 1006 * <ul> 1007 * <li>string</li> 1008 * <li>byte</li> 1009 * <li>short</li> 1010 * <li>integer</li> 1011 * <li>long</li> 1012 * <li>float</li> 1013 * <li>double</li> 1014 * <li>BigInteger</li> 1015 * <li>BigDecimal</li> 1016 * </ul> 1017 */ 1018 public static void contributeTranslatorSource(MappedConfiguration<Class, Translator> configuration, 1019 NumericTranslatorSupport support, Html5Support html5Support) 1020 { 1021 1022 configuration.add(String.class, new StringTranslator()); 1023 1024 Class[] types = new Class[] 1025 {Byte.class, Short.class, Integer.class, Long.class, Float.class, Double.class, BigInteger.class, 1026 BigDecimal.class}; 1027 1028 for (Class type : types) 1029 { 1030 String name = type.getSimpleName().toLowerCase(); 1031 1032 configuration.add(type, new NumericTranslator(name, type, support, html5Support)); 1033 } 1034 } 1035 1036 /** 1037 * Adds coercions: 1038 * <ul> 1039 * <li>String to {@link SelectModel} 1040 * <li>Map to {@link SelectModel} 1041 * <li>Collection to {@link GridDataSource} 1042 * <li>null to {@link GridDataSource} 1043 * <li>List to {@link SelectModel} 1044 * <li>{@link ComponentResourcesAware} (typically, a component) to {@link ComponentResources} 1045 * <li>{@link ComponentResources} to {@link PropertyOverrides} 1046 * <li>String to {@link Renderable} 1047 * <li>{@link Renderable} to {@link Block} 1048 * <li>String to {@link DateFormat} 1049 * <li>String to {@link Resource} (via {@link AssetSource#resourceForPath(String)}) 1050 * <li>{@link Renderable} to {@link RenderCommand}</li> 1051 * <li>String to {@link Pattern}</li> 1052 * <li>String to {@link DateFormat}</li> 1053 * <li>{@link Resource} to {@link DynamicTemplate}</li> 1054 * <li>{@link Asset} to {@link Resource}</li> 1055 * <li>{@link ValueEncoder} to {@link ValueEncoderFactory}</li> 1056 * </ul> 1057 */ 1058 public static void contributeTypeCoercer(MappedConfiguration<CoercionTuple.Key, CoercionTuple> configuration, 1059 1060 final ObjectLocator objectLocator, 1061 1062 @Builtin 1063 final ThreadLocale threadLocale, 1064 1065 @Core 1066 final AssetSource assetSource, 1067 1068 @Core 1069 final DynamicTemplateParser dynamicTemplateParser) 1070 { 1071 CoercionTuple<ComponentResources, PropertyOverrides> componentResourcesToPropertyOverrides = CoercionTuple.create(ComponentResources.class, PropertyOverrides.class, 1072 new Coercion<ComponentResources, PropertyOverrides>() 1073 { 1074 public PropertyOverrides coerce(ComponentResources input) 1075 { 1076 return new PropertyOverridesImpl(input); 1077 } 1078 }); 1079 configuration.add(componentResourcesToPropertyOverrides.getKey(), componentResourcesToPropertyOverrides); 1080 1081 1082 // See TAP5-2184 for why this causes some trouble! 1083 CoercionTuple<String, SelectModel> stringToSelectModel = CoercionTuple.create(String.class, SelectModel.class, new Coercion<String, SelectModel>() 1084 { 1085 public SelectModel coerce(String input) 1086 { 1087 return TapestryInternalUtils.toSelectModel(input); 1088 } 1089 }); 1090 configuration.add(stringToSelectModel.getKey(), stringToSelectModel); 1091 1092 CoercionTuple<Map, SelectModel> mapToSelectModel = CoercionTuple.create(Map.class, SelectModel.class, new Coercion<Map, SelectModel>() 1093 { 1094 @SuppressWarnings("unchecked") 1095 public SelectModel coerce(Map input) 1096 { 1097 return TapestryInternalUtils.toSelectModel(input); 1098 } 1099 }); 1100 configuration.add(mapToSelectModel.getKey(), mapToSelectModel); 1101 1102 CoercionTuple<Collection, GridDataSource> collectionToGridDataSource = CoercionTuple.create(Collection.class, GridDataSource.class, 1103 new Coercion<Collection, GridDataSource>() 1104 { 1105 public GridDataSource coerce(Collection input) 1106 { 1107 return new CollectionGridDataSource(input); 1108 } 1109 }); 1110 configuration.add(collectionToGridDataSource.getKey(), collectionToGridDataSource); 1111 1112 CoercionTuple<Void, GridDataSource> voidToGridDataSource = CoercionTuple.create(void.class, GridDataSource.class, new Coercion<Void, GridDataSource>() 1113 { 1114 private final GridDataSource source = new NullDataSource(); 1115 1116 public GridDataSource coerce(Void input) 1117 { 1118 return source; 1119 } 1120 }); 1121 configuration.add(voidToGridDataSource.getKey(), voidToGridDataSource); 1122 1123 CoercionTuple<List, SelectModel> listToSelectModel = CoercionTuple.create(List.class, SelectModel.class, new Coercion<List, SelectModel>() 1124 { 1125 private SelectModelFactory selectModelFactory; 1126 1127 @SuppressWarnings("unchecked") 1128 public SelectModel coerce(List input) 1129 { 1130 // This doesn't look thread safe, but it is because its a one-time transition from null 1131 // to another value, and a race condition is harmless. 1132 if (selectModelFactory == null) 1133 { 1134 selectModelFactory = objectLocator.getService(SelectModelFactory.class); 1135 } 1136 1137 return selectModelFactory.create(input); 1138 } 1139 }); 1140 configuration.add(listToSelectModel.getKey(), listToSelectModel); 1141 1142 CoercionTuple<String, Pattern> stringToPattern = CoercionTuple.create(String.class, Pattern.class, new Coercion<String, Pattern>() 1143 { 1144 public Pattern coerce(String input) 1145 { 1146 return Pattern.compile(input); 1147 } 1148 }); 1149 configuration.add(stringToPattern.getKey(), stringToPattern); 1150 1151 CoercionTuple<ComponentResourcesAware, ComponentResources> componentResourcesAwareToComponentResources = CoercionTuple.create(ComponentResourcesAware.class, ComponentResources.class, 1152 new Coercion<ComponentResourcesAware, ComponentResources>() 1153 { 1154 1155 public ComponentResources coerce(ComponentResourcesAware input) 1156 { 1157 return input.getComponentResources(); 1158 } 1159 }); 1160 configuration.add(componentResourcesAwareToComponentResources.getKey(), componentResourcesAwareToComponentResources); 1161 1162 CoercionTuple<String, Renderable> stringToRenderable = CoercionTuple.create(String.class, Renderable.class, new Coercion<String, Renderable>() 1163 { 1164 public Renderable coerce(String input) 1165 { 1166 return new StringRenderable(input); 1167 } 1168 }); 1169 configuration.add(stringToRenderable.getKey(), stringToRenderable); 1170 1171 CoercionTuple<Renderable, Block> renderableToBlock = CoercionTuple.create(Renderable.class, Block.class, new Coercion<Renderable, Block>() 1172 { 1173 public Block coerce(Renderable input) 1174 { 1175 return new RenderableAsBlock(input); 1176 } 1177 }); 1178 configuration.add(renderableToBlock.getKey(), renderableToBlock); 1179 1180 CoercionTuple<String, DateFormat> stringToDateFormat = CoercionTuple.create(String.class, DateFormat.class, new Coercion<String, DateFormat>() 1181 { 1182 public DateFormat coerce(String input) 1183 { 1184 final SimpleDateFormat dateFormat = new SimpleDateFormat(input, threadLocale.getLocale()); 1185 final String lenient = objectLocator.getService(SymbolSource.class).valueForSymbol(SymbolConstants.LENIENT_DATE_FORMAT); 1186 dateFormat.setLenient(Boolean.parseBoolean(lenient)); 1187 return dateFormat; 1188 } 1189 }); 1190 configuration.add(stringToDateFormat.getKey(), stringToDateFormat); 1191 1192 CoercionTuple<String, Resource> stringToResource = CoercionTuple.create(String.class, Resource.class, new Coercion<String, Resource>() 1193 { 1194 public Resource coerce(String input) 1195 { 1196 return assetSource.resourceForPath(input); 1197 } 1198 }); 1199 configuration.add(stringToResource.getKey(), stringToResource); 1200 1201 CoercionTuple<Renderable, RenderCommand> renderableToRenderCommand = CoercionTuple.create(Renderable.class, RenderCommand.class, 1202 new Coercion<Renderable, RenderCommand>() 1203 { 1204 public RenderCommand coerce(final Renderable input) 1205 { 1206 return new RenderCommand() 1207 { 1208 public void render(MarkupWriter writer, RenderQueue queue) 1209 { 1210 input.render(writer); 1211 } 1212 }; 1213 } 1214 }); 1215 configuration.add(renderableToRenderCommand.getKey(), renderableToRenderCommand); 1216 1217 CoercionTuple<Date, Calendar> dateToCalendar = CoercionTuple.create(Date.class, Calendar.class, new Coercion<Date, Calendar>() 1218 { 1219 public Calendar coerce(Date input) 1220 { 1221 Calendar calendar = Calendar.getInstance(threadLocale.getLocale()); 1222 calendar.setTime(input); 1223 return calendar; 1224 } 1225 }); 1226 configuration.add(dateToCalendar.getKey(), dateToCalendar); 1227 1228 CoercionTuple<Resource, DynamicTemplate> resourceToDynamicTemplate = CoercionTuple.create(Resource.class, DynamicTemplate.class, 1229 new Coercion<Resource, DynamicTemplate>() 1230 { 1231 public DynamicTemplate coerce(Resource input) 1232 { 1233 return dynamicTemplateParser.parseTemplate(input); 1234 } 1235 }); 1236 configuration.add(resourceToDynamicTemplate.getKey(), resourceToDynamicTemplate); 1237 1238 CoercionTuple<Asset, Resource> assetToResource = CoercionTuple.create(Asset.class, Resource.class, new Coercion<Asset, Resource>() 1239 { 1240 public Resource coerce(Asset input) 1241 { 1242 return input.getResource(); 1243 } 1244 }); 1245 configuration.add(assetToResource.getKey(), assetToResource); 1246 1247 CoercionTuple<ValueEncoder, ValueEncoderFactory> valueEncoderToValueEncoderFactory = CoercionTuple.create(ValueEncoder.class, ValueEncoderFactory.class, new Coercion<ValueEncoder, ValueEncoderFactory>() 1248 { 1249 public ValueEncoderFactory coerce(ValueEncoder input) 1250 { 1251 return new GenericValueEncoderFactory(input); 1252 } 1253 }); 1254 configuration.add(valueEncoderToValueEncoderFactory.getKey(), valueEncoderToValueEncoderFactory); 1255 } 1256 1257 /** 1258 * Adds built-in constraint generators: 1259 * <ul> 1260 * <li>PrimtiveField -- primitive fields are always required 1261 * <li>ValidateAnnotation -- adds constraints from a {@link Validate} annotation 1262 * </ul> 1263 */ 1264 public static void contributeValidationConstraintGenerator( 1265 OrderedConfiguration<ValidationConstraintGenerator> configuration) 1266 { 1267 configuration.add("PrimitiveField", new PrimitiveFieldConstraintGenerator()); 1268 configuration.add("ValidateAnnotation", new ValidateAnnotationConstraintGenerator()); 1269 configuration.addInstance("Messages", MessagesConstraintGenerator.class); 1270 } 1271 1272 private static void add(OrderedConfiguration<ComponentClassTransformWorker2> configuration, 1273 Class<? extends Annotation> annotationClass, MethodDescription description) 1274 { 1275 String name = TapestryInternalUtils.lastTerm(annotationClass.getName()); 1276 1277 ComponentClassTransformWorker2 worker = new PageLifecycleAnnotationWorker(annotationClass, 1278 description, name); 1279 1280 configuration.add(name, worker); 1281 } 1282 1283 // ======================================================================== 1284 // 1285 // Service Builder Methods (instance) 1286 // 1287 // ======================================================================== 1288 1289 public Context buildContext(ApplicationGlobals globals) 1290 { 1291 return shadowBuilder.build(globals, "context", Context.class); 1292 } 1293 1294 public static ComponentClassResolver buildComponentClassResolver(@Autobuild 1295 ComponentClassResolverImpl service, @ComponentClasses 1296 InvalidationEventHub hub) 1297 { 1298 // Allow the resolver to clean its cache when the component classes 1299 // change 1300 1301 hub.addInvalidationListener(service); 1302 1303 return service; 1304 } 1305 1306 1307 /** 1308 * Builds the PropBindingFactory as a chain of command. The terminator of 1309 * the chain is responsible for ordinary 1310 * property names (and property paths). 1311 * 1312 * This mechanism has been replaced in 5.1 with a more sophisticated parser based on ANTLR. See <a 1313 * href="https://issues.apache.org/jira/browse/TAP5-79">TAP5-79</a> for details. There are no longer any built-in 1314 * contributions to the configuration. 1315 * 1316 * @param configuration 1317 * contributions of special factories for some constants, each 1318 * contributed factory may return a 1319 * binding if applicable, or null otherwise 1320 */ 1321 public BindingFactory buildPropBindingFactory(List<BindingFactory> configuration, @Autobuild 1322 PropBindingFactory service) 1323 { 1324 configuration.add(service); 1325 1326 return chainBuilder.build(BindingFactory.class, configuration); 1327 } 1328 1329 public PersistentFieldStrategy buildClientPersistentFieldStrategy(LinkCreationHub linkCreationHub, @Autobuild 1330 ClientPersistentFieldStrategy service) 1331 { 1332 linkCreationHub.addListener(service); 1333 1334 return service; 1335 } 1336 1337 /** 1338 * Builds a proxy to the current {@link org.apache.tapestry5.services.ClientBehaviorSupport} inside this 1339 * thread's {@link org.apache.tapestry5.services.Environment}. 1340 * 1341 * @since 5.1.0.1 1342 */ 1343 1344 public ClientBehaviorSupport buildClientBehaviorSupport() 1345 { 1346 return environmentalBuilder.build(ClientBehaviorSupport.class); 1347 } 1348 1349 /** 1350 * Builds a proxy to the current {@link org.apache.tapestry5.services.FormSupport} inside this 1351 * thread's {@link org.apache.tapestry5.services.Environment}. 1352 */ 1353 public FormSupport buildFormSupport() 1354 { 1355 return environmentalBuilder.build(FormSupport.class); 1356 } 1357 1358 /** 1359 * Allows the exact steps in the component class transformation process to 1360 * be defined. 1361 */ 1362 @Marker(Primary.class) 1363 public ComponentClassTransformWorker2 buildComponentClassTransformWorker( 1364 List<ComponentClassTransformWorker2> configuration) 1365 1366 { 1367 return chainBuilder.build(ComponentClassTransformWorker2.class, configuration); 1368 } 1369 1370 /** 1371 * Analyzes properties to determine the data types, used to 1372 * {@linkplain #provideDefaultBeanBlocks(org.apache.tapestry5.commons.Configuration)} locale 1373 * display and edit blocks for properties. The default behaviors 1374 * look for a {@link org.apache.tapestry5.beaneditor.DataType} annotation 1375 * before deriving the data type from the property type. 1376 */ 1377 @Marker(Primary.class) 1378 public DataTypeAnalyzer buildDataTypeAnalyzer(List<DataTypeAnalyzer> configuration) 1379 { 1380 return chainBuilder.build(DataTypeAnalyzer.class, configuration); 1381 } 1382 1383 /** 1384 * A chain of command for providing values for {@link Inject}-ed fields in 1385 * component classes. The service's 1386 * configuration can be extended to allow for different automatic injections 1387 * (based on some combination of field 1388 * type and field name). 1389 */ 1390 public InjectionProvider2 buildInjectionProvider(List<InjectionProvider2> configuration) 1391 { 1392 return chainBuilder.build(InjectionProvider2.class, configuration); 1393 } 1394 1395 /** 1396 * The component event result processor used for normal component requests. 1397 */ 1398 @Marker( 1399 {Primary.class, Traditional.class}) 1400 public ComponentEventResultProcessor buildComponentEventResultProcessor( 1401 Map<Class, ComponentEventResultProcessor> configuration, @ComponentClasses 1402 InvalidationEventHub hub) 1403 { 1404 return constructComponentEventResultProcessor(configuration, hub); 1405 } 1406 1407 /** 1408 * The component event result processor used for Ajax-oriented component 1409 * requests. 1410 */ 1411 @Marker(Ajax.class) 1412 public ComponentEventResultProcessor buildAjaxComponentEventResultProcessor( 1413 Map<Class, ComponentEventResultProcessor> configuration, @ComponentClasses 1414 InvalidationEventHub hub) 1415 { 1416 return constructComponentEventResultProcessor(configuration, hub); 1417 } 1418 1419 private ComponentEventResultProcessor constructComponentEventResultProcessor( 1420 Map<Class, ComponentEventResultProcessor> configuration, InvalidationEventHub hub) 1421 { 1422 Set<Class> handledTypes = CollectionFactory.newSet(configuration.keySet()); 1423 1424 // A slight hack! 1425 1426 configuration.put(Object.class, new ObjectComponentEventResultProcessor(handledTypes)); 1427 1428 final StrategyRegistry<ComponentEventResultProcessor> registry = StrategyRegistry.newInstance( 1429 ComponentEventResultProcessor.class, configuration); 1430 1431 //As the registry will cache component classes, we need to clear the cache when we reload components to avoid memory leaks in permgen 1432 hub.addInvalidationCallback(new Runnable() 1433 { 1434 public void run() 1435 { 1436 registry.clearCache(); 1437 } 1438 }); 1439 1440 return strategyBuilder.build(registry); 1441 } 1442 1443 /** 1444 * The default data type analyzer is the final analyzer consulted and 1445 * identifies the type entirely pased on the 1446 * property type, working against its own configuration (mapping property 1447 * type class to data type). 1448 */ 1449 public static DataTypeAnalyzer buildDefaultDataTypeAnalyzer(@Autobuild 1450 DefaultDataTypeAnalyzer service, @ComponentClasses 1451 InvalidationEventHub hub) 1452 { 1453 hub.addInvalidationCallback(service); 1454 1455 return service; 1456 } 1457 1458 public static TranslatorSource buildTranslatorSource(Map<Class, Translator> configuration, 1459 TranslatorAlternatesSource alternatesSource, 1460 @ComponentClasses 1461 InvalidationEventHub hub) 1462 { 1463 TranslatorSourceImpl service = new TranslatorSourceImpl(configuration, 1464 alternatesSource.getTranslatorAlternates()); 1465 1466 hub.addInvalidationCallback(service); 1467 1468 return service; 1469 } 1470 1471 @Marker(Primary.class) 1472 public ObjectRenderer buildObjectRenderer(Map<Class, ObjectRenderer> configuration) 1473 { 1474 return strategyBuilder.build(ObjectRenderer.class, configuration); 1475 } 1476 1477 /** 1478 * Returns a {@link PlasticProxyFactory} that can be used to create extra classes around component classes. This 1479 * factory will be cleared whenever an underlying component class is discovered to have changed. Use of this 1480 * factory implies that your code will become aware of this (if necessary) to discard any cached object (alas, 1481 * this currently involves dipping into the internals side to register for the correct notifications). Failure to 1482 * properly clean up can result in really nasty PermGen space memory leaks. 1483 */ 1484 @Marker(ComponentLayer.class) 1485 public PlasticProxyFactory buildComponentProxyFactory(ComponentInstantiatorSource source) 1486 { 1487 return shadowBuilder.build(source, "proxyFactory", PlasticProxyFactory.class); 1488 } 1489 1490 /** 1491 * The MarkupRenderer service is used to render a full page as markup. 1492 * Supports an ordered configuration of {@link org.apache.tapestry5.services.MarkupRendererFilter}s. 1493 */ 1494 public MarkupRenderer buildMarkupRenderer(Logger logger, @Autobuild 1495 MarkupRendererTerminator terminator, List<MarkupRendererFilter> configuration) 1496 { 1497 return pipelineBuilder.build(logger, MarkupRenderer.class, MarkupRendererFilter.class, configuration, 1498 terminator); 1499 } 1500 1501 /** 1502 * A wrapper around {@link org.apache.tapestry5.internal.services.PageRenderQueue} used for 1503 * partial page renders. 1504 * Supports an ordered configuration of {@link org.apache.tapestry5.services.PartialMarkupRendererFilter}s. 1505 */ 1506 public PartialMarkupRenderer buildPartialMarkupRenderer(Logger logger, 1507 List<PartialMarkupRendererFilter> configuration, @Autobuild 1508 PartialMarkupRendererTerminator terminator) 1509 { 1510 return pipelineBuilder.build(logger, PartialMarkupRenderer.class, PartialMarkupRendererFilter.class, 1511 configuration, terminator); 1512 } 1513 1514 public PageRenderRequestHandler buildPageRenderRequestHandler(List<PageRenderRequestFilter> configuration, 1515 Logger logger, @Autobuild 1516 PageRenderRequestHandlerImpl terminator) 1517 { 1518 return pipelineBuilder.build(logger, PageRenderRequestHandler.class, PageRenderRequestFilter.class, 1519 configuration, terminator); 1520 } 1521 1522 /** 1523 * Builds the component action request handler for traditional (non-Ajax) 1524 * requests. These typically result in a 1525 * redirect to a Tapestry render URL. 1526 */ 1527 @Marker( 1528 {Traditional.class, Primary.class}) 1529 public ComponentEventRequestHandler buildComponentEventRequestHandler( 1530 List<ComponentEventRequestFilter> configuration, Logger logger, @Autobuild 1531 ComponentEventRequestHandlerImpl terminator) 1532 { 1533 return pipelineBuilder.build(logger, ComponentEventRequestHandler.class, ComponentEventRequestFilter.class, 1534 configuration, terminator); 1535 } 1536 1537 /** 1538 * Builds the action request handler for Ajax requests, based on a 1539 * {@linkplain org.apache.tapestry5.ioc.services.PipelineBuilder 1540 * pipeline} around {@link org.apache.tapestry5.internal.services.AjaxComponentEventRequestHandler} . Filters on 1541 * the 1542 * request handler are supported here as well. 1543 */ 1544 @Marker( 1545 {Ajax.class, Primary.class}) 1546 public ComponentEventRequestHandler buildAjaxComponentEventRequestHandler( 1547 List<ComponentEventRequestFilter> configuration, Logger logger, @Autobuild 1548 AjaxComponentEventRequestHandler terminator) 1549 { 1550 return pipelineBuilder.build(logger, ComponentEventRequestHandler.class, ComponentEventRequestFilter.class, 1551 configuration, terminator); 1552 } 1553 1554 // ======================================================================== 1555 // 1556 // Service Contribution Methods (instance) 1557 // 1558 // ======================================================================== 1559 1560 /** 1561 * Contributes the default "session" strategy. 1562 */ 1563 public void contributeApplicationStatePersistenceStrategySource( 1564 MappedConfiguration<String, ApplicationStatePersistenceStrategy> configuration, 1565 1566 @Local 1567 ApplicationStatePersistenceStrategy sessionStategy) 1568 { 1569 configuration.add("session", sessionStategy); 1570 } 1571 1572 /** 1573 * Contributes handlers for the following types: 1574 * <dl> 1575 * <dt>Object</dt> 1576 * <dd>Failure case, added to provide a more useful exception message</dd> 1577 * <dt>{@link Link}</dt> 1578 * <dd>Sends a redirect to the link (which is typically a page render link)</dd> 1579 * <dt>String</dt> 1580 * <dd>Sends a page render redirect</dd> 1581 * <dt>Class</dt> 1582 * <dd>Interpreted as the class name of a page, sends a page render render redirect (this is more refactoring safe 1583 * than the page name)</dd> 1584 * <dt>{@link Component}</dt> 1585 * <dd>A page's root component (though a non-root component will work, but will generate a warning). A direct to the 1586 * containing page is sent.</dd> 1587 * <dt>{@link org.apache.tapestry5.StreamResponse}</dt> 1588 * <dd>The stream response is sent as the actual reply.</dd> 1589 * <dt>URL</dt> 1590 * <dd>Sends a redirect to a (presumably) external URL</dd> 1591 * </dl> 1592 */ 1593 public void contributeComponentEventResultProcessor(@Traditional 1594 @ComponentInstanceProcessor 1595 ComponentEventResultProcessor componentInstanceProcessor, 1596 1597 MappedConfiguration<Class, ComponentEventResultProcessor> configuration) 1598 { 1599 configuration.add(Link.class, new ComponentEventResultProcessor<Link>() 1600 { 1601 public void processResultValue(Link value) throws IOException 1602 { 1603 response.sendRedirect(value); 1604 } 1605 }); 1606 1607 configuration.add(URL.class, new ComponentEventResultProcessor<URL>() 1608 { 1609 public void processResultValue(URL value) throws IOException 1610 { 1611 response.sendRedirect(value.toExternalForm()); 1612 } 1613 }); 1614 1615 configuration.addInstance(HttpError.class, HttpErrorComponentEventResultProcessor.class); 1616 configuration.addInstance(HttpStatus.class, HttpStatusComponentEventResultProcessor.class); 1617 1618 configuration.addInstance(String.class, PageNameComponentEventResultProcessor.class); 1619 1620 configuration.addInstance(Class.class, ClassResultProcessor.class); 1621 1622 configuration.add(Component.class, componentInstanceProcessor); 1623 1624 configuration.addInstance(StreamResponse.class, StreamResponseResultProcessor.class); 1625 1626 configuration.addInstance(StreamPageContent.class, StreamPageContentResultProcessor.class); 1627 1628 configuration.addInstance(JSONArray.class, JSONCollectionEventResultProcessor.class); 1629 configuration.addInstance(JSONObject.class, JSONCollectionEventResultProcessor.class); 1630 } 1631 1632 /** 1633 * Contributes handlers for the following types: 1634 * <dl> 1635 * <dt>Object</dt> 1636 * <dd>Failure case, added to provide more useful exception message</dd> 1637 * <dt>{@link RenderCommand}</dt> 1638 * <dd>Typically, a {@link org.apache.tapestry5.Block}</dd> 1639 * <dt>{@link org.apache.tapestry5.annotations.Component}</dt> 1640 * <dd>Renders the component and its body (unless its a page, in which case a redirect JSON response is sent)</dd> 1641 * <dt>{@link org.apache.tapestry5.json.JSONObject} or {@link org.apache.tapestry5.json.JSONArray}</dt> 1642 * <dd>The JSONObject is returned as a text/javascript response</dd> 1643 * <dt>{@link org.apache.tapestry5.StreamResponse}</dt> 1644 * <dd>The stream response is sent as the actual response</dd> 1645 * <dt>String</dt> 1646 * <dd>Interprets the value as a logical page name and sends a client response to redirect to that page</dd> 1647 * <dt>{@link org.apache.tapestry5.http.Link}</dt> 1648 * <dd>Sends a JSON response to redirect to the link</dd> 1649 * <dt>{@link Class}</dt> 1650 * <dd>Treats the class as a page class and sends a redirect for a page render for that page</dd> 1651 * <dt>{@link org.apache.tapestry5.ajax.MultiZoneUpdate}</dt> 1652 * <dd>Sends a single JSON response to update the content of multiple zones 1653 * </dl> 1654 * 1655 * In most cases, when you want to support a new type, you should convert it to one of the built-in supported types 1656 * (such as {@link RenderCommand}. You can then inject the master AjaxComponentEventResultProcessor (use the 1657 * {@link Ajax} marker annotation) and delegate to it. 1658 */ 1659 @Contribute(ComponentEventResultProcessor.class) 1660 @Ajax 1661 public static void provideBaseAjaxComponentEventResultProcessors( 1662 MappedConfiguration<Class, ComponentEventResultProcessor> configuration) 1663 { 1664 configuration.addInstance(RenderCommand.class, RenderCommandComponentEventResultProcessor.class); 1665 configuration.addInstance(Component.class, AjaxComponentInstanceEventResultProcessor.class); 1666 configuration.addInstance(JSONObject.class, JSONObjectEventResultProcessor.class); 1667 configuration.addInstance(JSONArray.class, JSONCollectionEventResultProcessor.class); 1668 configuration.addInstance(StreamResponse.class, StreamResponseResultProcessor.class); 1669 configuration.addInstance(String.class, AjaxPageNameComponentEventResultProcessor.class); 1670 configuration.addInstance(Link.class, AjaxLinkComponentEventResultProcessor.class); 1671 configuration.addInstance(URL.class, AjaxURLComponentEventResultProcessor.class); 1672 configuration.addInstance(Class.class, AjaxPageClassComponentEventResultProcessor.class); 1673 configuration.addInstance(MultiZoneUpdate.class, MultiZoneUpdateEventResultProcessor.class); 1674 configuration.addInstance(HttpError.class, HttpErrorComponentEventResultProcessor.class); 1675 } 1676 1677 /** 1678 * The MasterDispatcher is a chain-of-command of individual Dispatchers, 1679 * each handling (like a servlet) a particular 1680 * kind of incoming request. 1681 * <dl> 1682 * <dt>RootPath</dt> 1683 * <dd>Renders the start page for the "/" request (outdated)</dd> 1684 * <dt>PageRender</dt> 1685 * <dd>Identifies the {@link org.apache.tapestry5.services.PageRenderRequestParameters} and forwards onto 1686 * {@link PageRenderRequestHandler}</dd> 1687 * <dt>ComponentEvent</dt> 1688 * <dd>Identifies the {@link ComponentEventRequestParameters} and forwards onto the 1689 * {@link ComponentEventRequestHandler}</dd> 1690 * </dl> 1691 */ 1692 public static void contributeMasterDispatcher(OrderedConfiguration<Dispatcher> configuration, 1693 @Symbol(SymbolConstants.PUBLISH_OPENAPI_DEFINITON) final boolean publishOpenApiDefinition) 1694 { 1695 1696 if (publishOpenApiDefinition) 1697 { 1698 configuration.addInstance("OpenAPI", OpenApiDescriptionDispatcher.class, "before:PageRender", "before:ComponentEvent"); 1699 } 1700 1701 // Looks for the root path and renders the start page. This is 1702 // maintained for compatibility 1703 // with earlier versions of Tapestry 5, it is recommended that an Index 1704 // page be used instead. 1705 1706 configuration.addInstance("RootPath", RootPathDispatcher.class, "before:Asset"); 1707 1708 configuration.addInstance("ComponentEvent", ComponentEventDispatcher.class, "before:PageRender"); 1709 1710 configuration.addInstance("PageRender", PageRenderDispatcher.class); 1711 } 1712 1713 /** 1714 * Contributes a default object renderer for type Object, plus specialized 1715 * renderers for {@link org.apache.tapestry5.http.services.Request}, {@link org.apache.tapestry5.commons.Location}, 1716 * {@link org.apache.tapestry5.ComponentResources}, {@link org.apache.tapestry5.EventContext}, 1717 * {@link AvailableValues}, 1718 * List, and Object[]. 1719 */ 1720 @SuppressWarnings("unchecked") 1721 public void contributeObjectRenderer(MappedConfiguration<Class, ObjectRenderer> configuration, 1722 1723 @InjectService("LocationRenderer") 1724 ObjectRenderer locationRenderer, 1725 1726 final TypeCoercer typeCoercer) 1727 { 1728 configuration.add(Object.class, new DefaultObjectRenderer()); 1729 1730 configuration.addInstance(Request.class, RequestRenderer.class); 1731 1732 configuration.add(Location.class, locationRenderer); 1733 1734 ObjectRenderer preformatted = new ObjectRenderer<Object>() 1735 { 1736 public void render(Object object, MarkupWriter writer) 1737 { 1738 writer.element("pre"); 1739 writer.write(typeCoercer.coerce(object, String.class)); 1740 writer.end(); 1741 } 1742 }; 1743 1744 configuration.addInstance(List.class, ListRenderer.class); 1745 configuration.addInstance(Object[].class, ObjectArrayRenderer.class); 1746 configuration.addInstance(ComponentResources.class, ComponentResourcesRenderer.class); 1747 configuration.addInstance(EventContext.class, EventContextRenderer.class); 1748 configuration.add(AvailableValues.class, new AvailableValuesRenderer()); 1749 } 1750 1751 /** 1752 * Adds page render filters, each of which provides an {@link org.apache.tapestry5.annotations.Environmental} 1753 * service. Filters 1754 * often provide {@link org.apache.tapestry5.annotations.Environmental} services needed by 1755 * components as they render. 1756 * <dl> 1757 * <dt>DocumentLinker</dt> 1758 * <dd>Provides {@link org.apache.tapestry5.internal.services.DocumentLinker}</dd> 1759 * <dt>ClientBehaviorSupport (deprecated in 5.4)</dt> 1760 * <dd>Provides {@link ClientBehaviorSupport}</dd> 1761 * <dt>Heartbeat</dt> 1762 * <dd>Provides {@link org.apache.tapestry5.services.Heartbeat}</dd> 1763 * <dt>ValidationDecorator (deprecated in 5.4)</dt> 1764 * <dd>Provides {@link org.apache.tapestry5.ValidationDecorator} (via {@link ValidationDecoratorFactory#newInstance(org.apache.tapestry5.MarkupWriter)})</dd> 1765 * <dt>PageNameMeta (since 5.4)</dt> 1766 * <dd>Renders a {@code <meta/>} tag describing the active page name (development mode only)</dd> 1767 * <dt>ImportCoreStack (since 5.4) </dt> 1768 * <dd>Imports the "core" stack (necessary to get the Bootstrap CSS, if nothing else).</dd> 1769 * </dl> 1770 * 1771 * @see org.apache.tapestry5.SymbolConstants#OMIT_GENERATOR_META 1772 * @see org.apache.tapestry5.http.TapestryHttpSymbolConstants#PRODUCTION_MODE 1773 * @see org.apache.tapestry5.SymbolConstants#INCLUDE_CORE_STACK 1774 * @see org.apache.tapestry5.SymbolConstants#ENABLE_PAGELOADING_MASK 1775 */ 1776 public void contributeMarkupRenderer(OrderedConfiguration<MarkupRendererFilter> configuration, 1777 1778 final ModuleManager moduleManager, 1779 1780 @Symbol(SymbolConstants.OMIT_GENERATOR_META) 1781 final boolean omitGeneratorMeta, 1782 1783 @Symbol(TapestryHttpConstants.TAPESTRY_VERSION) 1784 final String tapestryVersion, 1785 1786 @Symbol(TapestryHttpSymbolConstants.PRODUCTION_MODE) 1787 boolean productionMode, 1788 1789 @Symbol(SymbolConstants.INCLUDE_CORE_STACK) 1790 final boolean includeCoreStack, 1791 1792 @Symbol(SymbolConstants.ENABLE_PAGELOADING_MASK) 1793 final boolean enablePageloadingMask, 1794 1795 final ValidationDecoratorFactory validationDecoratorFactory) 1796 { 1797 MarkupRendererFilter documentLinker = new MarkupRendererFilter() 1798 { 1799 public void renderMarkup(MarkupWriter writer, MarkupRenderer renderer) 1800 { 1801 DocumentLinkerImpl linker = new DocumentLinkerImpl(moduleManager, omitGeneratorMeta, enablePageloadingMask, tapestryVersion); 1802 1803 environment.push(DocumentLinker.class, linker); 1804 1805 renderer.renderMarkup(writer); 1806 1807 environment.pop(DocumentLinker.class); 1808 1809 linker.updateDocument(writer.getDocument()); 1810 } 1811 }; 1812 1813 1814 MarkupRendererFilter clientBehaviorSupport = new MarkupRendererFilter() 1815 { 1816 public void renderMarkup(MarkupWriter writer, MarkupRenderer renderer) 1817 { 1818 ClientBehaviorSupportImpl clientBehaviorSupport = new ClientBehaviorSupportImpl(); 1819 1820 environment.push(ClientBehaviorSupport.class, clientBehaviorSupport); 1821 1822 renderer.renderMarkup(writer); 1823 1824 environment.pop(ClientBehaviorSupport.class); 1825 } 1826 }; 1827 1828 MarkupRendererFilter heartbeat = new MarkupRendererFilter() 1829 { 1830 public void renderMarkup(MarkupWriter writer, MarkupRenderer renderer) 1831 { 1832 Heartbeat heartbeat = new HeartbeatImpl(); 1833 1834 heartbeat.begin(); 1835 1836 environment.push(Heartbeat.class, heartbeat); 1837 1838 renderer.renderMarkup(writer); 1839 1840 environment.pop(Heartbeat.class); 1841 1842 heartbeat.end(); 1843 } 1844 }; 1845 1846 MarkupRendererFilter defaultValidationDecorator = new MarkupRendererFilter() 1847 { 1848 public void renderMarkup(MarkupWriter writer, MarkupRenderer renderer) 1849 { 1850 ValidationDecorator decorator = validationDecoratorFactory.newInstance(writer); 1851 1852 environment.push(ValidationDecorator.class, decorator); 1853 1854 renderer.renderMarkup(writer); 1855 1856 environment.pop(ValidationDecorator.class); 1857 } 1858 }; 1859 1860 MarkupRendererFilter importCoreStack = new MarkupRendererFilter() 1861 { 1862 public void renderMarkup(MarkupWriter writer, MarkupRenderer renderer) 1863 { 1864 renderer.renderMarkup(writer); 1865 1866 environment.peekRequired(JavaScriptSupport.class).importStack(InternalConstants.CORE_STACK_NAME); 1867 } 1868 }; 1869 1870 configuration.add("DocumentLinker", documentLinker); 1871 configuration.add("ClientBehaviorSupport", clientBehaviorSupport, "after:JavaScriptSupport"); 1872 configuration.add("Heartbeat", heartbeat); 1873 configuration.add("ValidationDecorator", defaultValidationDecorator); 1874 1875 if (includeCoreStack) 1876 { 1877 configuration.add("ImportCoreStack", importCoreStack); 1878 } 1879 1880 if (productionMode) 1881 { 1882 configuration.add("PageNameMeta", null); 1883 } else 1884 { 1885 configuration.addInstance("PageNameMeta", PageNameMetaInjector.class); 1886 } 1887 } 1888 1889 /** 1890 * Contributes {@link PartialMarkupRendererFilter}s used when rendering a 1891 * partial Ajax response. 1892 * <dl> 1893 * <dt>DocumentLinker 1894 * <dd>Provides {@link org.apache.tapestry5.internal.services.DocumentLinker} 1895 * <dt>ClientBehaviorSupport</dt> 1896 * <dd>Provides {@link ClientBehaviorSupport}</dd> 1897 * <dt>Heartbeat</dt> 1898 * <dd>Provides {@link org.apache.tapestry5.services.Heartbeat}</dd> 1899 * <dt>DefaultValidationDecorator</dt> 1900 * <dt>ValidationDecorator</dt> 1901 * <dd>Provides {@link org.apache.tapestry5.ValidationDecorator} (via {@link ValidationDecoratorFactory#newInstance(org.apache.tapestry5.MarkupWriter)})</dd> 1902 * </dl> 1903 */ 1904 public void contributePartialMarkupRenderer(OrderedConfiguration<PartialMarkupRendererFilter> configuration, 1905 1906 final ValidationDecoratorFactory validationDecoratorFactory) 1907 { 1908 PartialMarkupRendererFilter documentLinker = new PartialMarkupRendererFilter() 1909 { 1910 public void renderMarkup(MarkupWriter writer, JSONObject reply, PartialMarkupRenderer renderer) 1911 { 1912 PartialMarkupDocumentLinker linker = new PartialMarkupDocumentLinker(); 1913 1914 environment.push(DocumentLinker.class, linker); 1915 1916 renderer.renderMarkup(writer, reply); 1917 1918 environment.pop(DocumentLinker.class); 1919 1920 linker.commit(reply); 1921 } 1922 }; 1923 1924 1925 PartialMarkupRendererFilter clientBehaviorSupport = new PartialMarkupRendererFilter() 1926 { 1927 public void renderMarkup(MarkupWriter writer, JSONObject reply, PartialMarkupRenderer renderer) 1928 { 1929 ClientBehaviorSupportImpl support = new ClientBehaviorSupportImpl(); 1930 1931 environment.push(ClientBehaviorSupport.class, support); 1932 1933 renderer.renderMarkup(writer, reply); 1934 1935 environment.pop(ClientBehaviorSupport.class); 1936 } 1937 }; 1938 1939 PartialMarkupRendererFilter heartbeat = new PartialMarkupRendererFilter() 1940 { 1941 public void renderMarkup(MarkupWriter writer, JSONObject reply, PartialMarkupRenderer renderer) 1942 { 1943 Heartbeat heartbeat = new HeartbeatImpl(); 1944 1945 heartbeat.begin(); 1946 1947 environment.push(Heartbeat.class, heartbeat); 1948 1949 renderer.renderMarkup(writer, reply); 1950 1951 environment.pop(Heartbeat.class); 1952 1953 heartbeat.end(); 1954 } 1955 }; 1956 1957 PartialMarkupRendererFilter defaultValidationDecorator = new PartialMarkupRendererFilter() 1958 { 1959 public void renderMarkup(MarkupWriter writer, JSONObject reply, PartialMarkupRenderer renderer) 1960 { 1961 ValidationDecorator decorator = validationDecoratorFactory.newInstance(writer); 1962 1963 environment.push(ValidationDecorator.class, decorator); 1964 1965 renderer.renderMarkup(writer, reply); 1966 1967 environment.pop(ValidationDecorator.class); 1968 } 1969 }; 1970 1971 configuration.add("DocumentLinker", documentLinker); 1972 configuration.add("ClientBehaviorSupport", clientBehaviorSupport, "after:JavaScriptSupport"); 1973 configuration.add("Heartbeat", heartbeat); 1974 configuration.add("ValidationDecorator", defaultValidationDecorator); 1975 } 1976 1977 /** 1978 * Contributes several strategies: 1979 * <dl> 1980 * <dt>session 1981 * <dd>Values are stored in the {@link Session} 1982 * <dt>flash 1983 * <dd>Values are stored in the {@link Session}, until the next request (for the page) 1984 * <dt>client 1985 * <dd>Values are encoded into URLs (or hidden form fields) 1986 * </dl> 1987 */ 1988 public void contributePersistentFieldManager(MappedConfiguration<String, PersistentFieldStrategy> configuration, 1989 1990 Request request, 1991 1992 @InjectService("ClientPersistentFieldStrategy") 1993 PersistentFieldStrategy clientStrategy) 1994 { 1995 configuration.add(PersistenceConstants.SESSION, new SessionPersistentFieldStrategy(request)); 1996 configuration.add(PersistenceConstants.FLASH, new FlashPersistentFieldStrategy(request)); 1997 configuration.add(PersistenceConstants.CLIENT, clientStrategy); 1998 } 1999 2000 /** 2001 * Contributes {@link ValueEncoder}s or {@link ValueEncoderFactory}s for types: 2002 * <ul> 2003 * <li>Object 2004 * <li>String 2005 * <li>Enum 2006 * </ul> 2007 */ 2008 @SuppressWarnings("all") 2009 public static void contributeValueEncoderSource(MappedConfiguration<Class, Object> configuration) 2010 { 2011 configuration.addInstance(Object.class, TypeCoercedValueEncoderFactory.class); 2012 configuration.add(String.class, new StringValueEncoder()); 2013 } 2014 2015 /** 2016 * Contributes a single filter, "Secure", which checks for non-secure 2017 * requests that access secure pages. 2018 */ 2019 public void contributePageRenderRequestHandler(OrderedConfiguration<PageRenderRequestFilter> configuration, 2020 final RequestSecurityManager securityManager) 2021 { 2022 PageRenderRequestFilter secureFilter = new PageRenderRequestFilter() 2023 { 2024 public void handle(PageRenderRequestParameters parameters, PageRenderRequestHandler handler) 2025 throws IOException 2026 { 2027 2028 if (securityManager.checkForInsecurePageRenderRequest(parameters)) 2029 return; 2030 2031 handler.handle(parameters); 2032 } 2033 }; 2034 2035 configuration.add("Secure", secureFilter); 2036 } 2037 2038 public static void contributeTemplateParser(MappedConfiguration<String, URL> config) 2039 { 2040 // Any class inside the internal module would do. Or we could move all 2041 // these 2042 // files to o.a.t.services. 2043 2044 Class c = TemplateParserImpl.class; 2045 2046 config.add("-//W3C//DTD XHTML 1.0 Strict//EN", c.getResource("xhtml1-strict.dtd")); 2047 config.add("-//W3C//DTD XHTML 1.0 Transitional//EN", c.getResource("xhtml1-transitional.dtd")); 2048 config.add("-//W3C//DTD XHTML 1.0 Frameset//EN", c.getResource("xhtml1-frameset.dtd")); 2049 config.add("-//W3C//DTD HTML 4.01//EN", c.getResource("xhtml1-strict.dtd")); 2050 config.add("-//W3C//DTD HTML 4.01 Transitional//EN", c.getResource("xhtml1-transitional.dtd")); 2051 config.add("-//W3C//DTD HTML 4.01 Frameset//EN", c.getResource("xhtml1-frameset.dtd")); 2052 config.add("-//W3C//ENTITIES Latin 1 for XHTML//EN", c.getResource("xhtml-lat1.ent")); 2053 config.add("-//W3C//ENTITIES Symbols for XHTML//EN", c.getResource("xhtml-symbol.ent")); 2054 config.add("-//W3C//ENTITIES Special for XHTML//EN", c.getResource("xhtml-special.ent")); 2055 } 2056 2057 /** 2058 * Contributes factory defaults that may be overridden. 2059 */ 2060 public static void contributeFactoryDefaults(MappedConfiguration<String, Object> configuration) 2061 { 2062 // Remember this is request-to-request time, presumably it'll take the 2063 // developer more than 2064 // one second to make a change, save it, and switch back to the browser. 2065 2066 configuration.add(SymbolConstants.FILE_CHECK_INTERVAL, "1 s"); 2067 configuration.add(SymbolConstants.FILE_CHECK_UPDATE_TIMEOUT, "50 ms"); 2068 2069 // This should be overridden for particular applications. These are the 2070 // locales for which we have (at least some) localized messages. 2071 configuration.add(SymbolConstants.SUPPORTED_LOCALES, 2072 "en,it,es,zh_CN,pt_PT,de,ru,hr,fi_FI,sv_SE,fr,da,pt_BR,ja,el,bg,nb,sr_RS,mk_MK"); 2073 2074 configuration.add(SymbolConstants.COOKIE_MAX_AGE, "7 d"); 2075 2076 configuration.add(SymbolConstants.START_PAGE_NAME, "start"); 2077 2078 configuration.add(TapestryHttpSymbolConstants.PRODUCTION_MODE, true); 2079 2080 configuration.add(SymbolConstants.COMPRESS_WHITESPACE, true); 2081 2082 configuration.add(MetaDataConstants.SECURE_PAGE, false); 2083 2084 configuration.add(SymbolConstants.FORM_CLIENT_LOGIC_ENABLED, true); 2085 2086 // This is designed to make it easy to keep synchronized with 2087 // script.aculo.ous. As we support a new version, we create a new folder, and update the 2088 // path entry. We can then delete the old version folder (or keep it around). This should 2089 // be more manageable than overwriting the local copy with updates (it's too easy for 2090 // files deleted between scriptaculous releases to be accidentally left lying around). 2091 // There's also a ClasspathAliasManager contribution based on the path. 2092 2093 configuration.add(SymbolConstants.SCRIPTACULOUS, "${tapestry.asset.root}/scriptaculous_1_9_0"); 2094 2095 // Likewise for WebFX DatePicker, currently version 1.0.6 2096 2097 configuration.add(SymbolConstants.DATEPICKER, "${tapestry.asset.root}/datepicker_106"); 2098 2099 configuration.add(SymbolConstants.PERSISTENCE_STRATEGY, PersistenceConstants.SESSION); 2100 2101 configuration.add(MetaDataConstants.RESPONSE_CONTENT_TYPE, "text/html"); 2102 2103 configuration.add(SymbolConstants.APPLICATION_CATALOG, 2104 String.format("context:WEB-INF/${%s}.properties", TapestryHttpInternalSymbols.APP_NAME)); 2105 2106 configuration.add(SymbolConstants.EXCEPTION_REPORT_PAGE, "ExceptionReport"); 2107 2108 configuration.add(SymbolConstants.OMIT_GENERATOR_META, false); 2109 2110 configuration.add(SymbolConstants.SECURE_ENABLED, SymbolConstants.PRODUCTION_MODE_VALUE); 2111 configuration.add(SymbolConstants.COMPACT_JSON, SymbolConstants.PRODUCTION_MODE_VALUE); 2112 2113 configuration.add(SymbolConstants.ENCODE_LOCALE_INTO_PATH, true); 2114 2115 configuration.add(InternalSymbols.RESERVED_FORM_CONTROL_NAMES, "reset,submit,select,id,method,action,onsubmit," + InternalConstants.CANCEL_NAME); 2116 2117 configuration.add(SymbolConstants.COMPONENT_RENDER_TRACING_ENABLED, false); 2118 2119 configuration.add(SymbolConstants.APPLICATION_FOLDER, ""); 2120 2121 // Grid component parameter defaults 2122 configuration.add(ComponentParameterConstants.GRID_ROWS_PER_PAGE, GridConstants.ROWS_PER_PAGE); 2123 configuration.add(ComponentParameterConstants.GRID_PAGER_POSITION, GridConstants.PAGER_POSITION); 2124 configuration.add(ComponentParameterConstants.GRID_EMPTY_BLOCK, GridConstants.EMPTY_BLOCK); 2125 configuration.add(ComponentParameterConstants.GRID_TABLE_CSS_CLASS, GridConstants.TABLE_CLASS); 2126 configuration.add(ComponentParameterConstants.GRIDPAGER_PAGE_RANGE, GridConstants.PAGER_PAGE_RANGE); 2127 configuration.add(ComponentParameterConstants.GRIDCOLUMNS_SORTABLE_ASSET, GridConstants.COLUMNS_SORTABLE); 2128 configuration.add(ComponentParameterConstants.GRIDCOLUMNS_ASCENDING_ASSET, GridConstants.COLUMNS_ASCENDING); 2129 configuration.add(ComponentParameterConstants.GRIDCOLUMNS_DESCENDING_ASSET, GridConstants.COLUMNS_DESCENDING); 2130 2131 // FormInjector component parameter defaults 2132 configuration.add(ComponentParameterConstants.FORMINJECTOR_INSERT_POSITION, "above"); 2133 configuration.add(ComponentParameterConstants.FORMINJECTOR_SHOW_FUNCTION, "highlight"); 2134 2135 // Palette component parameter defaults 2136 configuration.add(ComponentParameterConstants.PALETTE_ROWS_SIZE, 10); 2137 2138 // Defaults for components that use a SelectModel 2139 configuration.add(ComponentParameterConstants.VALIDATE_WITH_MODEL, SecureOption.AUTO); 2140 2141 // Zone component parameters defaults 2142 configuration.add(ComponentParameterConstants.ZONE_SHOW_METHOD, "show"); 2143 configuration.add(ComponentParameterConstants.ZONE_UPDATE_METHOD, "highlight"); 2144 2145 // By default, no page is on the whitelist unless it has the @WhitelistAccessOnly annotation 2146 configuration.add(MetaDataConstants.WHITELIST_ONLY_PAGE, false); 2147 2148 configuration.add(TapestryHttpSymbolConstants.CONTEXT_PATH, ""); 2149 2150 // Leaving this as the default results in a runtime error logged to the console (and a default password is used); 2151 // you are expected to override this symbol. 2152 configuration.add(SymbolConstants.HMAC_PASSPHRASE, ""); 2153 2154 // TAP5-2070 keep the old behavior, defaults to false 2155 configuration.add(MetaDataConstants.UNKNOWN_ACTIVATION_CONTEXT_CHECK, false); 2156 2157 // TAP5-2197 2158 configuration.add(SymbolConstants.INCLUDE_CORE_STACK, true); 2159 2160 // TAP5-2182 2161 configuration.add(SymbolConstants.FORM_GROUP_WRAPPER_CSS_CLASS, "form-group"); 2162 configuration.add(SymbolConstants.FORM_GROUP_LABEL_CSS_CLASS, "control-label"); 2163 configuration.add(SymbolConstants.FORM_GROUP_FORM_FIELD_WRAPPER_ELEMENT_NAME, ""); 2164 configuration.add(SymbolConstants.FORM_GROUP_FORM_FIELD_WRAPPER_ELEMENT_CSS_CLASS, ""); 2165 configuration.add(SymbolConstants.FORM_FIELD_CSS_CLASS, "form-control"); 2166 2167 // Grid's default table CSS class comes from the ComponentParameterConstants.GRID_TABLE_CSS_CLASS symbol 2168 configuration.add(SymbolConstants.BEAN_DISPLAY_CSS_CLASS, "well dl-horizontal"); 2169 configuration.add(SymbolConstants.BEAN_EDITOR_BOOLEAN_PROPERTY_DIV_CSS_CLASS, "input-group"); 2170 configuration.add(SymbolConstants.ERROR_CSS_CLASS, "help-block"); 2171 configuration.add(SymbolConstants.AJAX_FORM_LOOP_ADD_ROW_LINK_CSS_CLASS, "btn btn-default btn-sm"); 2172 configuration.add(SymbolConstants.ERRORS_BASE_CSS_CLASS, "alert-dismissable"); 2173 configuration.add(SymbolConstants.ERRORS_DEFAULT_CLASS_PARAMETER_VALUE, "alert alert-danger"); 2174 configuration.add(SymbolConstants.ERRORS_CLOSE_BUTTON_CSS_CLASS, "close"); 2175 2176 // TAP5-1998 2177 configuration.add(SymbolConstants.LENIENT_DATE_FORMAT, false); 2178 2179 // TAP5-2187 2180 configuration.add(SymbolConstants.STRICT_CSS_URL_REWRITING, false); 2181 2182 configuration.add(SymbolConstants.EXCEPTION_REPORTS_DIR, "build/exceptions"); 2183 2184 // TAP5-1815 2185 configuration.add(SymbolConstants.ENABLE_HTML5_SUPPORT, false); 2186 2187 configuration.add(SymbolConstants.RESTRICTIVE_ENVIRONMENT, false); 2188 2189 configuration.add(SymbolConstants.ENABLE_PAGELOADING_MASK, true); 2190 configuration.add(SymbolConstants.PRELOADER_MODE, PreloaderMode.PRODUCTION); 2191 2192 configuration.add(SymbolConstants.OPENAPI_VERSION, "3.0.0"); 2193 configuration.add(SymbolConstants.PUBLISH_OPENAPI_DEFINITON, "false"); 2194 configuration.add(SymbolConstants.OPENAPI_DESCRIPTION_PATH, "/openapi.json"); 2195 configuration.add(SymbolConstants.OPENAPI_BASE_PATH, "/"); 2196 } 2197 2198 /** 2199 * Adds a listener to the {@link org.apache.tapestry5.internal.services.ComponentInstantiatorSource} that clears the 2200 * {@link PropertyAccess} and {@link TypeCoercer} caches on 2201 * a class loader invalidation. In addition, forces the 2202 * realization of {@link ComponentClassResolver} at startup. 2203 */ 2204 public void contributeApplicationInitializer(OrderedConfiguration<ApplicationInitializerFilter> configuration, 2205 final TypeCoercer typeCoercer, final ComponentClassResolver componentClassResolver, @ComponentClasses 2206 final InvalidationEventHub invalidationEventHub, final @Autobuild 2207 RestoreDirtySessionObjects restoreDirtySessionObjects) 2208 { 2209 final Runnable callback = new Runnable() 2210 { 2211 public void run() 2212 { 2213 propertyAccess.clearCache(); 2214 2215 typeCoercer.clearCache(); 2216 } 2217 }; 2218 2219 ApplicationInitializerFilter clearCaches = new ApplicationInitializerFilter() 2220 { 2221 public void initializeApplication(Context context, ApplicationInitializer initializer) 2222 { 2223 // Snuck in here is the logic to clear the PropertyAccess 2224 // service's cache whenever 2225 // the component class loader is invalidated. 2226 2227 invalidationEventHub.addInvalidationCallback(callback); 2228 2229 endOfRequestEventHub.addEndOfRequestListener(restoreDirtySessionObjects); 2230 2231 // Perform other pending initialization 2232 2233 initializer.initializeApplication(context); 2234 2235 // We don't care about the result, but this forces a load of the 2236 // service 2237 // at application startup, rather than on first request. 2238 2239 componentClassResolver.isPageName("ForceLoadAtStartup"); 2240 } 2241 }; 2242 2243 configuration.add("ClearCachesOnInvalidation", clearCaches); 2244 } 2245 2246 /** 2247 * Contributes filters: 2248 * <dl> 2249 * <dt>Ajax</dt> 2250 * <dd>Determines if the request is Ajax oriented, and redirects to an alternative handler if so</dd> 2251 * <dt>Secure</dt> 2252 * <dd>Sends a redirect if an non-secure request accesses a secure page</dd> 2253 * </dl> 2254 */ 2255 public void contributeComponentEventRequestHandler(OrderedConfiguration<ComponentEventRequestFilter> configuration, 2256 final RequestSecurityManager requestSecurityManager, @Ajax 2257 ComponentEventRequestHandler ajaxHandler) 2258 { 2259 ComponentEventRequestFilter secureFilter = new ComponentEventRequestFilter() 2260 { 2261 public void handle(ComponentEventRequestParameters parameters, ComponentEventRequestHandler handler) 2262 throws IOException 2263 { 2264 if (requestSecurityManager.checkForInsecureComponentEventRequest(parameters)) 2265 return; 2266 2267 handler.handle(parameters); 2268 } 2269 }; 2270 configuration.add("Secure", secureFilter); 2271 2272 configuration.add("Ajax", new AjaxFilter(request, ajaxHandler)); 2273 } 2274 2275 /** 2276 * Contributes: 2277 * <dl> 2278 * <dt>AjaxFormUpdate</dt> 2279 * <dd>{@link AjaxFormUpdateFilter}</dd> 2280 * </dl> 2281 * 2282 * @since 5.2.0 2283 */ 2284 public static void contributeAjaxComponentEventRequestHandler( 2285 OrderedConfiguration<ComponentEventRequestFilter> configuration) 2286 { 2287 configuration.addInstance("AjaxFormUpdate", AjaxFormUpdateFilter.class); 2288 } 2289 2290 /** 2291 * Contributes strategies accessible via the {@link NullFieldStrategySource} service. 2292 * 2293 * <dl> 2294 * <dt>default</dt> 2295 * <dd>Does nothing, nulls stay null.</dd> 2296 * <dt>zero</dt> 2297 * <dd>Null values are converted to zero.</dd> 2298 * </dl> 2299 */ 2300 public static void contributeNullFieldStrategySource(MappedConfiguration<String, NullFieldStrategy> configuration) 2301 { 2302 configuration.add("default", new DefaultNullFieldStrategy()); 2303 configuration.add("zero", new ZeroNullFieldStrategy()); 2304 } 2305 2306 /** 2307 * Determines positioning of hidden fields relative to other elements (this 2308 * is needed by {@link org.apache.tapestry5.corelib.components.FormFragment} and others. 2309 * 2310 * For elements input, select, textarea and label the hidden field is positioned after. 2311 * 2312 * For elements p, div, li and td, the hidden field is positioned inside. 2313 */ 2314 public static void contributeHiddenFieldLocationRules( 2315 MappedConfiguration<String, RelativeElementPosition> configuration) 2316 { 2317 configuration.add("input", RelativeElementPosition.AFTER); 2318 configuration.add("select", RelativeElementPosition.AFTER); 2319 configuration.add("textarea", RelativeElementPosition.AFTER); 2320 configuration.add("label", RelativeElementPosition.AFTER); 2321 2322 configuration.add("p", RelativeElementPosition.INSIDE); 2323 configuration.add("div", RelativeElementPosition.INSIDE); 2324 configuration.add("td", RelativeElementPosition.INSIDE); 2325 configuration.add("li", RelativeElementPosition.INSIDE); 2326 } 2327 2328 /** 2329 * @since 5.1.0.0 2330 */ 2331 public static LinkCreationHub buildLinkCreationHub(LinkSource source) 2332 { 2333 return source.getLinkCreationHub(); 2334 } 2335 2336 /** 2337 * Exposes the public portion of the internal {@link InternalComponentInvalidationEventHub} service. 2338 * 2339 * @since 5.1.0.0 2340 */ 2341 @Marker(ComponentClasses.class) 2342 public static InvalidationEventHub buildComponentClassesInvalidationEventHub( 2343 InternalComponentInvalidationEventHub trueHub) 2344 { 2345 return trueHub; 2346 } 2347 2348 /** 2349 * @since 5.1.0.0 2350 */ 2351 @Marker(ComponentTemplates.class) 2352 public static InvalidationEventHub buildComponentTemplatesInvalidationEventHub( 2353 ComponentTemplateSource templateSource) 2354 { 2355 return templateSource.getInvalidationEventHub(); 2356 } 2357 2358 /** 2359 * @since 5.1.0.0 2360 */ 2361 @Marker(ComponentMessages.class) 2362 public static InvalidationEventHub buildComponentMessagesInvalidationEventHub(ComponentMessagesSource messagesSource) 2363 { 2364 return messagesSource.getInvalidationEventHub(); 2365 } 2366 2367 @Scope(ScopeConstants.PERTHREAD) 2368 public Environment buildEnvironment(PerthreadManager perthreadManager) 2369 { 2370 final EnvironmentImpl service = new EnvironmentImpl(); 2371 2372 perthreadManager.addThreadCleanupCallback(new Runnable() 2373 { 2374 public void run() 2375 { 2376 service.threadDidCleanup(); 2377 } 2378 }); 2379 2380 return service; 2381 } 2382 2383 /** 2384 * @since 5.1.1.0 2385 */ 2386 @Marker(Primary.class) 2387 public StackTraceElementAnalyzer buildMasterStackTraceElementAnalyzer(List<StackTraceElementAnalyzer> configuration) 2388 { 2389 return chainBuilder.build(StackTraceElementAnalyzer.class, configuration); 2390 } 2391 2392 /** 2393 * Contributes: 2394 * <dl> 2395 * <dt>Application</dt> 2396 * <dd>Checks for classes in the application package</dd> 2397 * <dt>Proxies</dt> 2398 * <dd>Checks for classes that appear to be generated proxies.</dd> 2399 * <dt>SunReflect</dt> 2400 * <dd>Checks for <code>sun.reflect</code> (which are omitted) 2401 * <dt>TapestryAOP</dt> 2402 * <dd>Omits stack frames for classes related to Tapestry AOP (such as advice, etc.)</dd> 2403 * <dt>OperationTracker</dt> 2404 * <dd>Omits stack frames related to {@link OperationTracker}</dd> 2405 * <dt>Access</dt> 2406 * <dd>Omits stack frames used to provide access to container class private members</dd> 2407 * </dl> 2408 * 2409 * @since 5.1.0.0 2410 */ 2411 public static void contributeMasterStackTraceElementAnalyzer( 2412 OrderedConfiguration<StackTraceElementAnalyzer> configuration) 2413 { 2414 configuration.addInstance("TapestryAOP", TapestryAOPStackFrameAnalyzer.class); 2415 configuration.add("Proxies", new ProxiesStackTraceElementAnalyzer()); 2416 configuration.add("Synthetic", new SyntheticStackTraceElementAnalyzer()); 2417 configuration.add("SunReflect", new PrefixCheckStackTraceElementAnalyzer( 2418 StackTraceElementClassConstants.OMITTED, "sun.reflect.")); 2419 configuration.add("OperationTracker", new RegexpStackTraceElementAnalyzer(Pattern.compile("internal\\.(RegistryImpl|PerThreadOperationTracker|OperationTrackerImpl).*(run|invoke|perform)\\("), StackTraceElementClassConstants.OMITTED)); 2420 configuration.add("Access", new RegexpStackTraceElementAnalyzer(Pattern.compile("\\.access\\$\\d+\\("), StackTraceElementClassConstants.OMITTED)); 2421 2422 configuration.addInstance("Application", ApplicationStackTraceElementAnalyzer.class); 2423 2424 } 2425 2426 2427 /** 2428 * Advises the {@link org.apache.tapestry5.services.messages.ComponentMessagesSource} service so 2429 * that the creation 2430 * of {@link org.apache.tapestry5.commons.Messages} instances can be deferred. 2431 * 2432 * @since 5.1.0.0 2433 */ 2434 @Match("ComponentMessagesSource") 2435 public static void adviseLazy(LazyAdvisor advisor, MethodAdviceReceiver receiver) 2436 { 2437 advisor.addLazyMethodInvocationAdvice(receiver); 2438 } 2439 2440 /** 2441 * @since 5.1.0.0 2442 */ 2443 public ComponentRequestHandler buildComponentRequestHandler(List<ComponentRequestFilter> configuration, 2444 2445 @Autobuild 2446 ComponentRequestHandlerTerminator terminator, 2447 2448 Logger logger) 2449 { 2450 return pipelineBuilder.build(logger, ComponentRequestHandler.class, ComponentRequestFilter.class, 2451 configuration, terminator); 2452 } 2453 2454 /** 2455 * Contributes: 2456 * <dl> 2457 * <dt>OperationTracker</dt> 2458 * <dd>Tracks general information about the request using {@link OperationTracker}</dd> 2459 * <dt>UnknownComponentFilter (production mode only)</dt> 2460 * <dd>{@link org.apache.tapestry5.internal.services.ProductionModeUnknownComponentFilter} - Detects request with unknown component and aborts handling to ultimately deliver a 404 response</dd> 2461 * <dt>InitializeActivePageName 2462 * <dd>{@link InitializeActivePageName} 2463 * <dt>DeferredResponseRenderer</dt> 2464 * <dd>{@link DeferredResponseRenderer}</dd> 2465 * </dl> 2466 * 2467 * @since 5.2.0 2468 */ 2469 public void contributeComponentRequestHandler(OrderedConfiguration<ComponentRequestFilter> configuration, @Symbol(TapestryHttpSymbolConstants.PRODUCTION_MODE) boolean productionMode) 2470 { 2471 configuration.addInstance("OperationTracker", RequestOperationTracker.class); 2472 2473 if (productionMode) 2474 { 2475 configuration.addInstance("UnknownComponentFilter", ProductionModeUnknownComponentFilter.class); 2476 } 2477 2478 configuration.addInstance("InitializeActivePageName", InitializeActivePageName.class); 2479 configuration.addInstance("DeferredResponseRenderer", DeferredResponseRenderer.class); 2480 } 2481 2482 /** 2483 * Decorate FieldValidatorDefaultSource to setup the EnvironmentMessages 2484 * object and place it in the environment. 2485 * Although this could have been implemented directly in the default 2486 * implementation of the service, doing it 2487 * as service decoration ensures that the environment will be properly setup 2488 * even if a user overrides the default 2489 * service implementation. 2490 * 2491 * @param defaultSource 2492 * The service to decorate 2493 * @param environment 2494 */ 2495 public static FieldValidatorDefaultSource decorateFieldValidatorDefaultSource( 2496 final FieldValidatorDefaultSource defaultSource, final Environment environment) 2497 { 2498 return new FieldValidatorDefaultSource() 2499 { 2500 2501 public FieldValidator createDefaultValidator(Field field, String overrideId, Messages overrideMessages, 2502 Locale locale, Class propertyType, AnnotationProvider propertyAnnotations) 2503 { 2504 environment.push(EnvironmentMessages.class, new EnvironmentMessages(overrideMessages, overrideId)); 2505 FieldValidator fieldValidator = defaultSource.createDefaultValidator(field, overrideId, 2506 overrideMessages, locale, propertyType, propertyAnnotations); 2507 environment.pop(EnvironmentMessages.class); 2508 return fieldValidator; 2509 } 2510 2511 public FieldValidator createDefaultValidator(ComponentResources resources, String parameterName) 2512 { 2513 2514 EnvironmentMessages em = new EnvironmentMessages(resources.getContainerMessages(), resources.getId()); 2515 environment.push(EnvironmentMessages.class, em); 2516 FieldValidator fieldValidator = defaultSource.createDefaultValidator(resources, parameterName); 2517 environment.pop(EnvironmentMessages.class); 2518 return fieldValidator; 2519 } 2520 }; 2521 } 2522 2523 /** 2524 * Exposes the Environmental {@link Heartbeat} as an injectable service. 2525 * 2526 * @since 5.2.0 2527 */ 2528 public Heartbeat buildHeartbeat() 2529 { 2530 return environmentalBuilder.build(Heartbeat.class); 2531 } 2532 2533 public static ComponentMessagesSource buildComponentMessagesSource(UpdateListenerHub updateListenerHub, @Autobuild 2534 ComponentMessagesSourceImpl service) 2535 { 2536 updateListenerHub.addUpdateListener(service); 2537 2538 return service; 2539 } 2540 2541 /** 2542 * Contributes extractors for {@link Meta}, {@link Secure}, {@link ContentType} and {@link WhitelistAccessOnly} annotations. 2543 * 2544 * @since 5.2.0 2545 */ 2546 @SuppressWarnings("unchecked") 2547 public static void contributeMetaWorker(MappedConfiguration<Class, MetaDataExtractor> configuration) 2548 { 2549 configuration.addInstance(Meta.class, MetaAnnotationExtractor.class); 2550 configuration.add(Secure.class, new FixedExtractor(MetaDataConstants.SECURE_PAGE)); 2551 configuration.addInstance(ContentType.class, ContentTypeExtractor.class); 2552 configuration.add(WhitelistAccessOnly.class, new FixedExtractor(MetaDataConstants.WHITELIST_ONLY_PAGE)); 2553 configuration.addInstance(UnknownActivationContextCheck.class, UnknownActivationContextExtractor.class); 2554 } 2555 2556 /** 2557 * Builds the {@link ComponentTemplateLocator} as a chain of command. 2558 * 2559 * @since 5.2.0 2560 */ 2561 @Marker(Primary.class) 2562 public ComponentTemplateLocator buildComponentTemplateLocator(List<ComponentTemplateLocator> configuration) 2563 { 2564 return chainBuilder.build(ComponentTemplateLocator.class, configuration); 2565 } 2566 2567 /** 2568 * Contributes two template locators: 2569 * <dl> 2570 * <dt>Default</dt> 2571 * <dd>Searches for the template on the classpath ({@link DefaultTemplateLocator}</dd> 2572 * <dt>Page</dt> 2573 * <dd>Searches for <em>page</em> templates in the context ({@link PageTemplateLocator})</dd> 2574 * </dl> 2575 * 2576 * @since 5.2.0 2577 */ 2578 public static void contributeComponentTemplateLocator(OrderedConfiguration<ComponentTemplateLocator> configuration, 2579 @ContextProvider 2580 AssetFactory contextAssetFactory, 2581 @Symbol(SymbolConstants.APPLICATION_FOLDER) String applicationFolder, 2582 ComponentClassResolver componentClassResolver) 2583 { 2584 configuration.add("Default", new DefaultTemplateLocator()); 2585 configuration 2586 .add("Page", new PageTemplateLocator(contextAssetFactory.getRootResource(), componentClassResolver, applicationFolder)); 2587 2588 } 2589 2590 /** 2591 * Builds {@link ComponentEventLinkTransformer} service as a chain of command. 2592 * 2593 * @since 5.2.0 2594 */ 2595 @Marker(Primary.class) 2596 public ComponentEventLinkTransformer buildComponentEventLinkTransformer( 2597 List<ComponentEventLinkTransformer> configuration) 2598 { 2599 return chainBuilder.build(ComponentEventLinkTransformer.class, configuration); 2600 } 2601 2602 /** 2603 * Builds {@link PageRenderLinkTransformer} service as a chain of command. 2604 * 2605 * @since 5.2.0 2606 */ 2607 @Marker(Primary.class) 2608 public PageRenderLinkTransformer buildPageRenderLinkTransformer(List<PageRenderLinkTransformer> configuration) 2609 { 2610 return chainBuilder.build(PageRenderLinkTransformer.class, configuration); 2611 } 2612 2613 /** 2614 * Provides the "LinkTransformer" interceptor for the {@link ComponentEventLinkEncoder} service. 2615 * Other decorations 2616 * should come after LinkTransformer. 2617 * 2618 * @since 5.2.0 2619 */ 2620 @Match("ComponentEventLinkEncoder") 2621 public ComponentEventLinkEncoder decorateLinkTransformer(LinkTransformer linkTransformer, 2622 ComponentEventLinkEncoder delegate) 2623 { 2624 return new LinkTransformerInterceptor(linkTransformer, delegate); 2625 } 2626 2627 /** 2628 * In production mode, override {@link UpdateListenerHub} to be an empty placeholder. 2629 */ 2630 @Contribute(ServiceOverride.class) 2631 public static void productionModeOverrides(MappedConfiguration<Class, Object> configuration, 2632 @Symbol(TapestryHttpSymbolConstants.PRODUCTION_MODE) 2633 boolean productionMode) 2634 { 2635 if (productionMode) 2636 { 2637 configuration.add(UpdateListenerHub.class, new UpdateListenerHub() 2638 { 2639 public void fireCheckForUpdates() 2640 { 2641 } 2642 2643 public void addUpdateListener(UpdateListener listener) 2644 { 2645 2646 } 2647 }); 2648 } 2649 } 2650 2651 /** 2652 * Contributes a single default analyzer: 2653 * <dl> 2654 * <dt>LocalhostOnly</dt> 2655 * <dd>Identifies requests from localhost as on client whitelist</dd> 2656 * </dl> 2657 * 2658 * @since 5.3 2659 */ 2660 @Contribute(ClientWhitelist.class) 2661 public static void defaultWhitelist(OrderedConfiguration<WhitelistAnalyzer> configuration) 2662 { 2663 configuration.add("LocalhostOnly", new LocalhostOnly()); 2664 } 2665 2666 @Startup 2667 public static void registerToClearPlasticProxyFactoryOnInvalidation(@ComponentClasses InvalidationEventHub hub, @Builtin final PlasticProxyFactory proxyFactory) 2668 { 2669 hub.addInvalidationCallback(new Runnable() 2670 { 2671 public void run() 2672 { 2673 proxyFactory.clearCache(); 2674 } 2675 }); 2676 } 2677 2678 /** 2679 * @since 5.4 2680 */ 2681 @Contribute(ValueLabelProvider.class) 2682 public void defaultValueLabelProviders(MappedConfiguration<Class, ValueLabelProvider> configuration) 2683 { 2684 configuration.addInstance(Object.class, DefaultValueLabelProvider.class); 2685 configuration.addInstance(Enum.class, EnumValueLabelProvider.class); 2686 } 2687 2688 /** 2689 * @since 5.4 2690 */ 2691 public ValueLabelProvider<?> buildValueLabelProvider(Map<Class, ValueLabelProvider> configuration) 2692 { 2693 return strategyBuilder.build(ValueLabelProvider.class, configuration); 2694 } 2695 2696 @Advise(serviceInterface = ComponentInstantiatorSource.class) 2697 public static void componentReplacer(MethodAdviceReceiver methodAdviceReceiver, 2698 final ComponentOverride componentReplacer) throws NoSuchMethodException, SecurityException 2699 { 2700 2701 if (componentReplacer.hasReplacements()) 2702 { 2703 2704 MethodAdvice advice = new MethodAdvice() 2705 { 2706 @Override 2707 public void advise(MethodInvocation invocation) 2708 { 2709 String className = (String) invocation.getParameter(0); 2710 final Class<?> replacement = componentReplacer.getReplacement(className); 2711 if (replacement != null) 2712 { 2713 invocation.setParameter(0, replacement.getName()); 2714 } 2715 invocation.proceed(); 2716 } 2717 }; 2718 2719 methodAdviceReceiver.adviseMethod( 2720 ComponentInstantiatorSource.class.getMethod("getInstantiator", String.class), advice); 2721 2722 } 2723 } 2724 2725 public static ComponentLibraryInfoSource buildComponentLibraryInfoSource(List<ComponentLibraryInfoSource> configuration, 2726 ChainBuilder chainBuilder) 2727 { 2728 return chainBuilder.build(ComponentLibraryInfoSource.class, configuration); 2729 } 2730 2731 @Contribute(ComponentLibraryInfoSource.class) 2732 public static void addBuiltInComponentLibraryInfoSources(OrderedConfiguration<ComponentLibraryInfoSource> configuration) 2733 { 2734 configuration.addInstance("Maven", MavenComponentLibraryInfoSource.class); 2735 configuration.add("TapestryCore", new TapestryCoreComponentLibraryInfoSource()); 2736 } 2737 2738 public static OpenApiDescriptionGenerator buildOpenApiDocumentationGenerator(List<OpenApiDescriptionGenerator> configuration, 2739 ChainBuilder chainBuilder) 2740 { 2741 return chainBuilder.build(OpenApiDescriptionGenerator.class, configuration); 2742 } 2743 2744 public static OpenApiTypeDescriber buildOpenApiTypeDescriber(List<OpenApiTypeDescriber> configuration, 2745 ChainBuilder chainBuilder) 2746 { 2747 return chainBuilder.build(OpenApiTypeDescriber.class, configuration); 2748 } 2749 2750 @Contribute(OpenApiDescriptionGenerator.class) 2751 public static void addBuiltInOpenApiDocumentationGenerator( 2752 OrderedConfiguration<OpenApiDescriptionGenerator> configuration) { 2753 configuration.addInstance("Default", DefaultOpenApiDescriptionGenerator.class, "before:*"); 2754 } 2755 2756 @Contribute(OpenApiTypeDescriber.class) 2757 public static void addBuiltInOpenApiTypeDescriber( 2758 OrderedConfiguration<OpenApiTypeDescriber> configuration) { 2759 configuration.addInstance("Default", DefaultOpenApiTypeDescriber.class, "before:*"); 2760 } 2761 2762 /** 2763 * Contributes the package "<root>.rest.entities" to the configuration, 2764 * so that it will be scanned for mapped entity classes. 2765 */ 2766 public static void contributeMappedEntityManager(Configuration<String> configuration, 2767 @Symbol(TapestryHttpInternalConstants.TAPESTRY_APP_PACKAGE_PARAM) String appRootPackage) 2768 { 2769 configuration.add(appRootPackage + ".rest.entities"); 2770 } 2771 2772 private static final class TapestryCoreComponentLibraryInfoSource implements 2773 ComponentLibraryInfoSource 2774 { 2775 @Override 2776 public ComponentLibraryInfo find(LibraryMapping libraryMapping) 2777 { 2778 ComponentLibraryInfo info = null; 2779 if (libraryMapping.libraryName.equals("core")) 2780 { 2781 2782 info = new ComponentLibraryInfo(); 2783 2784 // the information above will probably not change in the future, or change very 2785 // infrequently, so I see no problem in hardwiring them here. 2786 info.setArtifactId("tapestry-core"); 2787 info.setGroupId("org.apache.tapestry"); 2788 info.setName("Tapestry 5 core component library"); 2789 info.setDescription("Components provided out-of-the-box by Tapestry"); 2790 info.setDocumentationUrl("http://tapestry.apache.org/component-reference.html"); 2791 info.setJavadocUrl("http://tapestry.apache.org/current/apidocs/"); 2792 info.setSourceBrowseUrl("https://git-wip-us.apache.org/repos/asf?p=tapestry-5.git;a=summary"); 2793 info.setSourceRootUrl("https://git-wip-us.apache.org/repos/asf?p=tapestry-5.git;a=blob;f=tapestry-core/src/main/java/"); 2794 info.setIssueTrackerUrl("https://issues.apache.org/jira/browse/TAP5"); 2795 info.setHomepageUrl("http://tapestry.apache.org"); 2796 info.setLibraryMapping(libraryMapping); 2797 2798 final InputStream inputStream = TapestryModule.class.getResourceAsStream( 2799 "/META-INF/gradle/org.apache.tapestry/tapestry-core/project.properties"); 2800 2801 if (inputStream != null) 2802 { 2803 Properties properties = new Properties(); 2804 try 2805 { 2806 properties.load(inputStream); 2807 } catch (IOException e) 2808 { 2809 throw new RuntimeException(e); 2810 } 2811 info.setVersion(properties.getProperty("version")); 2812 } 2813 } 2814 return info; 2815 } 2816 } 2817 2818}