You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by hl...@apache.org on 2007/03/11 20:11:04 UTC
svn commit: r516990 [2/2] - in
/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry:
internal/services/InternalModule.java services/TapestryModule.java
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java?view=diff&rev=516990&r1=516989&r2=516990
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java Sun Mar 11 12:11:03 2007
@@ -199,232 +199,141 @@
@SubModule(InternalModule.class)
public final class TapestryModule
{
- private final ChainBuilder _chainBuilder;
-
- private final PipelineBuilder _pipelineBuilder;
-
- private final RequestGlobals _requestGlobals;
-
- private final ApplicationGlobals _applicationGlobals;
-
- private final PropertyShadowBuilder _shadowBuilder;
-
- private final RequestPageCache _requestPageCache;
-
- private final PageResponseRenderer _pageResponseRenderer;
-
- private final Request _request;
-
- private final Environment _environment;
-
- private final StrategyBuilder _strategyBuilder;
-
- // Primarily used as a InvalidationEventHub for service implementations
- // that should clear their cache when the underlying component class loader
- // is discarded.
-
- private final ComponentInstantiatorSource _componentInstantiatorSource;
-
- private final LinkFactory _linkFactory;
-
- private final PropertyAccess _propertyAccess;
-
- private final PropertyConduitSource _propertyConduitSource;
-
- private final ClassFactory _componentClassFactory;
-
- // Yes, you can inject services defined by this module into this module. The service proxy is
- // created without instantiating the module itself. We're careful about making as many
- // service builder and contributor methods static as possible to avoid recursive build
- // exceptions.
-
- public TapestryModule(@InjectService("PipelineBuilder")
- PipelineBuilder pipelineBuilder,
-
- @InjectService("PropertyShadowBuilder")
- PropertyShadowBuilder shadowBuilder,
-
- @Inject("infrastructure:RequestGlobals")
- RequestGlobals requestGlobals,
+ public static MarkupWriterFactory build(@InjectService("ComponentInvocationMap")
+ final ComponentInvocationMap componentInvocationMap)
+ {
+ // Temporary ...
+ return new MarkupWriterFactory()
+ {
+ public MarkupWriter newMarkupWriter()
+ {
+ return new MarkupWriterImpl(new DefaultMarkupModel(), componentInvocationMap);
+ }
+ };
+ }
- @Inject("infrastructure:ApplicationGlobals")
- ApplicationGlobals applicationGlobals,
+ public static ClasspathAssetAliasManager build(@InjectService("ContextPathSource")
+ ContextPathSource contextPathSource, Map<String, String> configuration)
+ {
+ return new ClasspathAssetAliasManagerImpl(contextPathSource, configuration);
+ }
- @InjectService("ChainBuilder")
- ChainBuilder chainBuilder,
+ public static PersistentLocale build(@InjectService("Cookies")
+ Cookies cookies)
+ {
+ return new PersistentLocaleImpl(cookies);
+ }
- @InjectService("RequestPageCache")
- RequestPageCache requestPageCache,
+ public static Infrastructure build(Log log,
- @InjectService("PageResponseRenderer")
- PageResponseRenderer pageResponseRenderer,
+ @InjectService("InfrastructureOverrides")
+ InfrastructureManager overridesManager,
- @Inject("infrastructure:Request")
- Request request,
+ Collection<InfrastructureContribution> configuration)
+ {
+ InfrastructureManager manager = new InfrastructureManagerImpl(log, configuration);
- @Inject("infrastructure:Environment")
- Environment environment,
+ return new InfrastructureImpl(manager, overridesManager);
+ }
- @InjectService("StrategyBuilder")
- StrategyBuilder strategyBuilder,
+ public static ApplicationStateManager build(
+ Map<Class, ApplicationStateContribution> configuration,
+ @Inject("infrastructure:ApplicationStatePersistenceStrategySource")
+ ApplicationStatePersistenceStrategySource source)
+ {
+ return new ApplicationStateManagerImpl(configuration, source);
+ }
- @InjectService("ComponentInstantiatorSource")
- ComponentInstantiatorSource componentInstantiatorSource,
+ public static ApplicationStatePersistenceStrategySource build(
+ Map<String, ApplicationStatePersistenceStrategy> configuration)
+ {
+ return new ApplicationStatePersistenceStrategySourceImpl(configuration);
+ }
- @InjectService("LinkFactory")
- LinkFactory linkFactory,
+ public static BindingSource build(Map<String, BindingFactory> configuration)
+ {
+ return new BindingSourceImpl(configuration);
+ }
- @Inject("infrastructure:PropertyConduitSource")
- PropertyConduitSource propertyConduitSource,
+ public static TranslatorSource build(Map<String, Translator> configuration)
+ {
+ return new TranslatorSourceImpl(configuration);
+ }
- @Inject("infrastructure:PropertyAccess")
- PropertyAccess propertyAccess,
+ /** A public service since extensions may provide new persistent strategies. */
+ public static PersistentFieldManager build(@Inject("infrastructure:MetaDataLocator")
+ MetaDataLocator locator,
- @InjectService("ComponentClassFactory")
- ClassFactory componentClassFactory)
+ Map<String, PersistentFieldStrategy> configuration)
{
- _pipelineBuilder = pipelineBuilder;
- _shadowBuilder = shadowBuilder;
- _requestGlobals = requestGlobals;
- _applicationGlobals = applicationGlobals;
- _chainBuilder = chainBuilder;
- _requestPageCache = requestPageCache;
- _pageResponseRenderer = pageResponseRenderer;
- _request = request;
- _environment = environment;
- _strategyBuilder = strategyBuilder;
- _componentInstantiatorSource = componentInstantiatorSource;
- _linkFactory = linkFactory;
- _propertyAccess = propertyAccess;
- _propertyConduitSource = propertyConduitSource;
- _componentClassFactory = componentClassFactory;
+ return new PersistentFieldManagerImpl(locator, configuration);
}
- /**
- * Invoked from
- * {@link #contributeInfrastructure(Configuration, ServiceLocator, Request, Response, TypeCoercer)}
- * to contribute services from the tapestry module where the unqualified class name of the
- * service interface matches the unqualified service id. This unqualified name is used as the
- * infrastructure alias.
- */
- @SuppressWarnings("unchecked")
- private static void add(Configuration<InfrastructureContribution> configuration,
- ServiceLocator locator, Class... serviceInterfaces)
- {
- for (Class serviceInterface : serviceInterfaces)
- {
- String serviceId = TapestryInternalUtils.lastTerm(serviceInterface.getName());
+ public static FieldValidatorSource build(@Inject("infrastructure:ValidationMessagesSource")
+ ValidationMessagesSource messagesSource,
- Object service = locator.getService(serviceId, serviceInterface);
+ @Inject("infrastructure:TypeCoercer")
+ TypeCoercer typeCoercer,
- InfrastructureContribution contribution = new InfrastructureContribution(serviceId,
- service);
+ @Inject("service:PageRenderSupport")
+ PageRenderSupport pageRenderSupport,
- configuration.add(contribution);
- }
+ Map<String, Validator> configuration)
+ {
+ return new FieldValidatorSourceImpl(messagesSource, typeCoercer, pageRenderSupport,
+ configuration);
}
+ // Primarily used as a InvalidationEventHub for service implementations
+ // that should clear their cache when the underlying component class loader
+ // is discarded.
+
public static ApplicationGlobals buildApplicationGlobals()
{
return new ApplicationGlobalsImpl();
}
- public Context buildContext(@InjectService("ApplicationGlobals")
- ApplicationGlobals globals)
+ public static AssetSource buildAssetSource(Map<String, AssetFactory> configuration)
{
- return _shadowBuilder.build(globals, "context", Context.class);
+ return new AssetSourceImpl(configuration);
}
- public ServletApplicationInitializer buildServletApplicationInitializer(Log log,
- List<ServletApplicationInitializerFilter> configuration,
- @InjectService("ApplicationInitializer")
- final ApplicationInitializer initializer)
- {
- ServletApplicationInitializer terminator = new ServletApplicationInitializer()
- {
- public void initializeApplication(ServletContext context)
- {
- _applicationGlobals.store(context);
-
- // And now, down the (Web) ApplicationInitializer pipeline ...
+ public static Cookies buildCookies(@InjectService("ContextPathSource")
+ ContextPathSource contextPathSource,
- initializer.initializeApplication(new ContextImpl(context));
- }
- };
+ @InjectService("CookieSource")
+ CookieSource cookieSource,
- return _pipelineBuilder.build(
- log,
- ServletApplicationInitializer.class,
- ServletApplicationInitializerFilter.class,
- configuration,
- terminator);
- }
+ @InjectService("CookieSink")
+ CookieSink cookieSink,
- /** Initializes the application. */
- public ApplicationInitializer buildApplicationInitializer(Log log,
- List<ApplicationInitializerFilter> configuration)
+ @Inject("${tapestry.default-cookie-max-age}")
+ int defaultMaxAge)
{
- ApplicationInitializer terminator = new ApplicationInitializer()
- {
- public void initializeApplication(Context context)
- {
- _applicationGlobals.store(context);
- }
- };
-
- return _pipelineBuilder.build(
- log,
- ApplicationInitializer.class,
- ApplicationInitializerFilter.class,
- configuration,
- terminator);
+ return new CookiesImpl(contextPathSource, cookieSource, cookieSink, defaultMaxAge);
}
- /**
- * Allows the exact steps in the component class transformation process to be defined.
- */
- public ComponentClassTransformWorker buildComponentClassTransformWorker(
- List<ComponentClassTransformWorker> configuration)
+ @Lifecycle("perthread")
+ public static Environment buildEnvironment()
{
- return _chainBuilder.build(ComponentClassTransformWorker.class, configuration);
+ return new EnvironmentImpl();
}
- public HttpServletRequestHandler buildHttpServletRequestHandler(Log log,
- List<HttpServletRequestFilter> configuration,
+ public static FieldValidatorDefaultSource buildFieldValidatorDefaultSource(
+ @Inject("infrastructure:ValidationConstraintGenerator")
+ ValidationConstraintGenerator validationConstraintGenerator,
- @InjectService("RequestHandler")
- final RequestHandler handler)
+ @Inject("infrastructure:FieldValidatorSource")
+ FieldValidatorSource fieldValidatorSource)
{
- HttpServletRequestHandler terminator = new HttpServletRequestHandler()
- {
- public boolean service(HttpServletRequest request, HttpServletResponse response)
- throws IOException
- {
- _requestGlobals.store(request, response);
-
- return handler.service(new RequestImpl(request), new ResponseImpl(response));
- }
- };
-
- return _pipelineBuilder.build(
- log,
- HttpServletRequestHandler.class,
- HttpServletRequestFilter.class,
- configuration,
- terminator);
+ return new FieldValidatorDefaultSourceImpl(validationConstraintGenerator,
+ fieldValidatorSource);
}
- public static Infrastructure buildInfrastructure(Log log,
-
- @InjectService("InfrastructureOverrides")
- InfrastructureManager overridesManager,
-
- Collection<InfrastructureContribution> configuration)
- {
- InfrastructureManager manager = new InfrastructureManagerImpl(log, configuration);
-
- return new InfrastructureImpl(manager, overridesManager);
- }
+ // Yes, you can inject services defined by this module into this module. The service proxy is
+ // created without instantiating the module itself. We're careful about making as many
+ // service builder and contributor methods static as possible to avoid recursive build
+ // exceptions.
/**
* A companion service to {@link #buildInfrastructure(Log, Collection)} whose configuration
@@ -436,118 +345,268 @@
return new InfrastructureManagerImpl(log, configuration);
}
- public static MarkupWriterFactory buildMarkupWriterFactory(
- @InjectService("ComponentInvocationMap")
- final ComponentInvocationMap componentInvocationMap)
+ @Lifecycle("perthread")
+ public static RequestGlobals buildRequestGlobals()
{
- // Temporary ...
- return new MarkupWriterFactory()
- {
- public MarkupWriter newMarkupWriter()
- {
- return new MarkupWriterImpl(new DefaultMarkupModel(), componentInvocationMap);
- }
- };
+ return new RequestGlobalsImpl();
}
- /**
- * Ordered contributions to the MasterDispatcher service allow different URL matching strategies
- * to occur.
- */
- public Dispatcher buildMasterDispatcher(List<Dispatcher> configuration)
+ public static ResourceDigestGenerator buildResourceDigestGenerator()
{
- return _chainBuilder.build(Dispatcher.class, configuration);
+ return new ResourceDigestGeneratorImpl();
}
- @Lifecycle("perthread")
- public static RequestGlobals buildRequestGlobals()
+ public static ValidationConstraintGenerator buildValidationConstraintGenerator(
+ List<ValidationConstraintGenerator> configuration)
{
- return new RequestGlobalsImpl();
+ return new ValidationConstraintGeneratorImpl(configuration);
}
/**
- * Builds a shadow of the RequestGlobals.request property. Note again that the shadow can be an
- * ordinary singleton, even though RequestGlobals is perthread.
+ * Contributes the factory for serveral built-in binding prefixes ("literal", prop", "block",
+ * "component" "message", "validate", "translate").
*/
- public Request buildRequest()
+ public static void contributeBindingSource(
+ MappedConfiguration<String, BindingFactory> configuration,
+
+ @InjectService("PropBindingFactory")
+ BindingFactory propBindingFactory,
+
+ @Inject("infrastructure:FieldValidatorSource")
+ FieldValidatorSource fieldValidatorSource,
+
+ @Inject("infrastructure:TranslatorSource")
+ TranslatorSource translatorSource)
{
- return _shadowBuilder.build(_requestGlobals, "request", Request.class);
+ configuration.add(TapestryConstants.LITERAL_BINDING_PREFIX, new LiteralBindingFactory());
+ configuration.add(TapestryConstants.PROP_BINDING_PREFIX, propBindingFactory);
+ configuration.add("component", new ComponentBindingFactory());
+ configuration.add("message", new MessageBindingFactory());
+ configuration.add("validate", new ValidateBindingFactory(fieldValidatorSource));
+ configuration.add("translate", new TranslateBindingFactory(translatorSource));
+ configuration.add("block", new BlockBindingFactory());
}
- /**
- * Builds a shadow of the RequestGlobals.response property. Note again that the shadow can be an
- * ordinary singleton, even though RequestGlobals is perthread.
- */
- public Response buildResponse()
+ public static void contributeClasspathAssetAliasManager(
+ MappedConfiguration<String, String> configuration,
+
+ @Inject("${tapestry.scriptaculous.path}")
+ String scriptaculousPath)
{
- return _shadowBuilder.build(_requestGlobals, "response", Response.class);
+ configuration.add("tapestry/", "org/apache/tapestry/");
+
+ configuration.add("scriptaculous/", scriptaculousPath + "/");
}
- public RequestHandler buildRequestHandler(Log log, List<RequestFilter> configuration,
- @InjectService("MasterDispatcher")
- final Dispatcher masterDispatcher)
+ public static void contributeComponentClassResolver(Configuration<LibraryMapping> configuration)
{
- RequestHandler terminator = new RequestHandler()
- {
- public boolean service(Request request, Response response) throws IOException
- {
- _requestGlobals.store(request, response);
+ configuration.add(new LibraryMapping("core", "org.apache.tapestry.corelib"));
+ }
- return masterDispatcher.dispatch(request, response);
- }
- };
+ /**
+ * Adds a number of standard component class transform workers:
+ * <ul>
+ * <li>Retain -- allows fields to retain their values between requests</li>
+ * <li>Persist -- allows fields to store their their value persistently between requests</li>
+ * <li>Parameter -- identifies parameters based on the
+ * {@link org.apache.tapestry.annotations.Parameter} annotation</li>
+ * <li>Component -- identifies embedded components based on the
+ * {@link org.apache.tapestry.annotations.Component} annotation</li>
+ * <li>Mixin -- adds a mixin as part of a component's implementation</li>
+ * <li>Environment -- allows fields to contain values extracted from the {@link Environment}
+ * service</li>
+ * <li>InjectNamed -- used with the {@link Inject} annotation, when a value is supplied</li>
+ * <li>InjectAnnonymous -- used with the {@link Inject} annotation, when no value is supplied</li>
+ * <li>InjectPage -- adds code to allow access to other pages via the {@link InjectPage} field
+ * annotation</li>
+ * <li>InjectBlock -- allows a block from the template to be injected into a field</li>
+ * <li>SupportsInformalParameters -- checks for the annotation</li>
+ * <li>Meta -- checks for meta data and adds it to the component model
+ * <li>ApplicationState -- converts fields that reference application state objects
+ * <li>UnclaimedField -- identifies unclaimed fields and resets them to null/0/false at the end
+ * of the request</li>
+ * <li>RenderCommand -- ensures all components also implement {@link RenderCommand}</li>
+ * <li>SetupRender, BeginRender, etc. -- correspond to component render phases and annotations</li>
+ * </ul>
+ */
+ public static void contributeComponentClassTransformWorker(
+ OrderedConfiguration<ComponentClassTransformWorker> configuration,
- return _pipelineBuilder.build(
- log,
- RequestHandler.class,
- RequestFilter.class,
+ ServiceLocator locator,
+
+ @InjectService("MasterObjectProvider")
+ ObjectProvider objectProvider,
+
+ @InjectService("InjectionProvider")
+ InjectionProvider injectionProvider,
+
+ @Inject("infrastructure:Environment")
+ Environment environment,
+
+ @Inject("infrastructure:ComponentClassResolver")
+ ComponentClassResolver resolver,
+
+ @InjectService("RequestPageCache")
+ RequestPageCache requestPageCache,
+
+ @Inject("infrastructure:AssetSource")
+ AssetSource assetSource,
+
+ @InjectService("SymbolSource")
+ SymbolSource symbolSource,
+
+ @Inject("infrastructure:BindingSource")
+ BindingSource bindingsource,
+
+ @Inject("infrastructure:ApplicationStateManager")
+ ApplicationStateManager applicationStateManager)
+ {
+ // TODO: Proper scheduling of all of this. Since a given field or method should
+ // only have a single annotation, the order doesn't matter so much, as long as
+ // UnclaimedField is last.
+
+ configuration.add("Meta", new MetaWorker());
+ configuration.add("ApplicationState", new ApplicationStateWorker(applicationStateManager));
+ configuration.add("InjectNamed", new InjectNamedWorker(objectProvider, locator));
+ configuration.add(
+ "InjectAnonymous",
+ new InjectAnonymousWorker(locator, injectionProvider),
+ "after:InjectNamed");
+ configuration.add(
+ "InjectAsset",
+ new InjectAssetWorker(assetSource, symbolSource),
+ "before:InjectNamed");
+ configuration.add("InjectBlock", new InjectBlockWorker(), "before:InjectNamed");
+
+ configuration.add("MixinAfter", new MixinAfterWorker());
+ configuration.add("Component", new ComponentWorker(resolver));
+ configuration.add("Environment", new EnvironmentalWorker(environment));
+ configuration.add("Mixin", new MixinWorker(resolver));
+ configuration.add("OnEvent", new OnEventWorker());
+ configuration.add("SupportsInformalParameters", new SupportsInformalParametersWorker());
+ configuration.add("InjectPage", new InjectPageWorker(requestPageCache));
+ configuration.add("InjectComponent", new InjectComponentWorker());
+ configuration.add("RenderCommand", new RenderCommandWorker());
+
+ // Default values for parameters are often some form of injection, so make sure
+ // that Parameter fields are processed after injections.
+
+ configuration.add("Parameter", new ParameterWorker(bindingsource), "after:Inject*");
+
+ // Workers for the component rendering state machine methods; this is in typical
+ // execution order.
+
+ add(configuration, TransformConstants.SETUP_RENDER_SIGNATURE, SetupRender.class, false);
+ add(configuration, TransformConstants.BEGIN_RENDER_SIGNATURE, BeginRender.class, false);
+ add(
configuration,
- terminator);
+ TransformConstants.BEFORE_RENDER_TEMPLATE_SIGNATURE,
+ BeforeRenderTemplate.class,
+ false);
+ add(
+ configuration,
+ TransformConstants.BEFORE_RENDER_BODY_SIGNATURE,
+ BeforeRenderBody.class,
+ false);
+
+ // These phases operate in reverse order.
+
+ add(
+ configuration,
+ TransformConstants.AFTER_RENDER_BODY_SIGNATURE,
+ AfterRenderBody.class,
+ true);
+ add(
+ configuration,
+ TransformConstants.AFTER_RENDER_TEMPLATE_SIGNATURE,
+ AfterRenderTemplate.class,
+ true);
+ add(configuration, TransformConstants.AFTER_RENDER_SIGNATURE, AfterRender.class, true);
+ add(configuration, TransformConstants.CLEANUP_RENDER_SIGNATURE, CleanupRender.class, true);
+
+ // Ideally, these should be ordered pretty late in the process to make sure there are no
+ // side effects
+ // with other workers that do work inside the page lifecycle methods.
+
+ add(
+ configuration,
+ PageLoaded.class,
+ TransformConstants.CONTAINING_PAGE_DID_LOAD_SIGNATURE,
+ "pageLoaded");
+ add(
+ configuration,
+ PageAttached.class,
+ TransformConstants.CONTAINING_PAGE_DID_ATTACH_SIGNATURE,
+ "pageAttached");
+ add(
+ configuration,
+ PageDetached.class,
+ TransformConstants.CONTAINING_PAGE_DID_DETACH_SIGNATURE,
+ "pageDetached");
+
+ configuration.add("Retain", new RetainWorker());
+ configuration.add("Persist", new PersistWorker());
+ configuration.add("UnclaimedField", new UnclaimedFieldWorker(), "after:*.*");
}
/**
- * Contributes filter "StaticFilesFilter" that identifies requests for static resources and
- * terminates the pipeline by returning false. Generally, most filters should be ordered after
- * this filter.
+ * Adds the {@link #buildDefaultDataTypeAnalyzer(Map) DefaultDatatTypeAnalyzer} to the
+ * configuration, ordered explicitly last.
*/
- public static void contributeRequestHandler(OrderedConfiguration<RequestFilter> configuration,
- @InjectService("Context")
- Context context,
-
- @Inject("infrastructure:RequestExceptionHandler")
- final RequestExceptionHandler exceptionHandler)
+ public static void contributeDataTypeAnalyzer(
+ OrderedConfiguration<DataTypeAnalyzer> configuration,
+ @InjectService("DefaultDataTypeAnalyzer")
+ DataTypeAnalyzer defaultDataTypeAnalyzer)
{
- RequestFilter staticFilesFilter = new StaticFilesFilter(context);
+ configuration.add("Default", defaultDataTypeAnalyzer, "after:*");
+ }
- configuration.add("StaticFiles", staticFilesFilter);
+ /**
+ * Maps property types to data type names
+ * <ul>
+ * <li>String --> text
+ * <li>Number --> text
+ * <li>Enum --> enum
+ * <li>Boolean --> checkbox
+ * </ul>
+ */
+ public static void contributeDefaultDataTypeAnalyzer(
+ MappedConfiguration<Class, String> configuration)
+ {
+ // This is a special case contributed to avoid exceptions when a property type can't be
+ // matched. DefaultDataTypeAnalyzer converts the empty string to null.
- RequestFilter errorFilter = new RequestFilter()
- {
- public boolean service(Request request, Response response, RequestHandler handler)
- throws IOException
- {
- try
- {
- return handler.service(request, response);
- }
- catch (IOException ex)
- {
- // Pass it through.
- throw ex;
- }
- catch (Throwable ex)
- {
- exceptionHandler.handleRequestException(ex);
+ configuration.add(Object.class, "");
- // We assume a reponse has been sent and there's no need to handle the request
- // further.
+ configuration.add(String.class, "text");
- return true;
- }
- }
- };
+ // This may change; as currently implemented, "text" refers more to the edit component
+ // (TextField) than to
+ // the "flavor" of data.
- configuration.add("ErrorFilter", errorFilter);
+ configuration.add(Number.class, "text");
+ configuration.add(Enum.class, "enum");
+ configuration.add(Boolean.class, "checkbox");
+ }
+
+ /**
+ * Contributes the basic set of validators:
+ * <ul>
+ * <li>required</li>
+ * <li>minlength</li>
+ * <li>maxlength</li>
+ * <li>min</li>
+ * <li>max</li>
+ * </ul>
+ */
+ public static void contributeFieldValidatorSource(
+ MappedConfiguration<String, Validator> configuration)
+ {
+ configuration.add("required", new Required());
+ configuration.add("minlength", new MinLength());
+ configuration.add("maxlength", new MaxLength());
+ configuration.add("min", new Min());
+ configuration.add("max", new Max());
}
/**
@@ -603,6 +662,22 @@
}
/**
+ * Contributes the elemental providers:
+ * <ul>
+ * <li>ComponentResources -- give component access to its resources</li>
+ * <li>CommonResources -- access to properties of resources (log, messages, etc.)</li>
+ * <li>Default -- looks for a unique IoC service that matches the field type</li>
+ * </ul>
+ */
+ public static void contributeInjectionProvider(
+ OrderedConfiguration<InjectionProvider> configuration)
+ {
+ configuration.add("ComponentResources", new ComponentResourcesInjectionProvider());
+ configuration.add("CommonResources", new CommonResourcesInjectionProvider());
+ configuration.add("Default", new DefaultInjectionProvider(), "after:*.*");
+ }
+
+ /**
* Contributes the {@link ObjectProvider} provided by {@link Infrastructure#getObjectProvider()}
* mapped to the provider prefix "infrastructure".
*/
@@ -633,296 +708,200 @@
configuration.add("infrastructure", wrapper);
}
- public void contributeMasterDispatcher(OrderedConfiguration<Dispatcher> configuration,
- @Inject("infrastructure:ClasspathAssetAliasManager")
- ClasspathAssetAliasManager aliasManager,
-
- @InjectService("ResourceCache")
- ResourceCache resourceCache,
-
- @InjectService("ResourceStreamer")
- ResourceStreamer streamer,
-
- @InjectService("PageLinkHandler")
- PageLinkHandler pageLinkHandler,
-
- @InjectService("ActionLinkHandler")
- ActionLinkHandler actionLinkHandler,
-
- @InjectService("ComponentClassResolver")
- ComponentClassResolver componentClassResolver,
-
- @Inject("${tapestry.start-page-name}")
- String startPageName)
- {
- // Looks for the root path and renders the start page
-
- configuration.add("RootPath", new RootPathDispatcher(componentClassResolver,
- pageLinkHandler, _pageResponseRenderer, startPageName), "before:Asset");
-
- // This goes first because an asset to be streamed may have an file extension, such as
- // ".html", that will confuse the later dispatchers.
-
- configuration.add(
- "Asset",
- new AssetDispatcher(streamer, aliasManager, resourceCache),
- "before:PageRender");
-
- configuration.add("PageRender", new PageRenderDispatcher(componentClassResolver,
- pageLinkHandler, _pageResponseRenderer));
-
- configuration.add(
- "ComponentAction",
- new ComponentActionDispatcher(actionLinkHandler),
- "after:PageRender");
- }
-
- public ComponentClassResolver buildComponentClassResolver(
- Collection<LibraryMapping> configuration)
- {
- ComponentClassResolverImpl service = new ComponentClassResolverImpl(
- _componentInstantiatorSource, new ComponentClassLocatorImpl(), configuration);
-
- // Allow the resolver to clean its cache when the source is invalidated
-
- _componentInstantiatorSource.addInvalidationListener(service);
-
- return service;
- }
-
- public static void contributeComponentClassResolver(Configuration<LibraryMapping> configuration)
- {
- configuration.add(new LibraryMapping("core", "org.apache.tapestry.corelib"));
- }
-
- public static BindingSource buildBindingSource(Map<String, BindingFactory> configuration)
- {
- return new BindingSourceImpl(configuration);
- }
-
/**
- * Contributes the factory for serveral built-in binding prefixes ("literal", prop", "block",
- * "component" "message", "validate", "translate").
+ * Contributes filter "StaticFilesFilter" that identifies requests for static resources and
+ * terminates the pipeline by returning false. Generally, most filters should be ordered after
+ * this filter.
*/
- public static void contributeBindingSource(
- MappedConfiguration<String, BindingFactory> configuration,
+ public static void contributeRequestHandler(OrderedConfiguration<RequestFilter> configuration,
+ @InjectService("Context")
+ Context context,
- @InjectService("PropBindingFactory")
- BindingFactory propBindingFactory,
+ @Inject("infrastructure:RequestExceptionHandler")
+ final RequestExceptionHandler exceptionHandler)
+ {
+ RequestFilter staticFilesFilter = new StaticFilesFilter(context);
- @Inject("infrastructure:FieldValidatorSource")
- FieldValidatorSource fieldValidatorSource,
+ configuration.add("StaticFiles", staticFilesFilter);
- @Inject("infrastructure:TranslatorSource")
- TranslatorSource translatorSource)
- {
- configuration.add(TapestryConstants.LITERAL_BINDING_PREFIX, new LiteralBindingFactory());
- configuration.add(TapestryConstants.PROP_BINDING_PREFIX, propBindingFactory);
- configuration.add("component", new ComponentBindingFactory());
- configuration.add("message", new MessageBindingFactory());
- configuration.add("validate", new ValidateBindingFactory(fieldValidatorSource));
- configuration.add("translate", new TranslateBindingFactory(translatorSource));
- configuration.add("block", new BlockBindingFactory());
- }
+ RequestFilter errorFilter = new RequestFilter()
+ {
+ public boolean service(Request request, Response response, RequestHandler handler)
+ throws IOException
+ {
+ try
+ {
+ return handler.service(request, response);
+ }
+ catch (IOException ex)
+ {
+ // Pass it through.
+ throw ex;
+ }
+ catch (Throwable ex)
+ {
+ exceptionHandler.handleRequestException(ex);
- /**
- * Returns a {@link ClassFactory} that can be used to create extra classes around component
- * classes. This ClassFactory will be cleared whenever an underlying component class is
- * discovered to have changed. Use of this class factory implies that your code will become
- * aware of this (if necessary) to discard any cached object (alas, this currently involves
- * dipping into the internals side to register for the correct notifications). Failure to
- * properly clean up can result in really nasty PermGen space memory leaks.
- */
- public ClassFactory buildComponentClassFactory()
- {
- return _shadowBuilder.build(
- _componentInstantiatorSource,
- "classFactory",
- ClassFactory.class);
- }
+ // We assume a reponse has been sent and there's no need to handle the request
+ // further.
- /**
- * A chain of command for providing values for {@link org.apache.tapestry.annotations.Inject}-ed
- * fields in component classes. The service's configuration can be extended to allow for
- * different automatic injections (based on some combination of field type and field name).
- */
+ return true;
+ }
+ }
+ };
- public InjectionProvider buildInjectionProvider(List<InjectionProvider> configuration)
- {
- return _chainBuilder.build(InjectionProvider.class, configuration);
+ configuration.add("ErrorFilter", errorFilter);
}
/**
- * Contributes the elemental providers:
+ * Contributes the basic set of default translators:
* <ul>
- * <li>ComponentResources -- give component access to its resources</li>
- * <li>CommonResources -- access to properties of resources (log, messages, etc.)</li>
- * <li>Default -- looks for a unique IoC service that matches the field type</li>
- * </ul>
+ * <li>Integer</li>
+ * <li>String</li>
+ * <li>Long</li>
+ * <li>Double</li>
+ * </li>
*/
- public static void contributeInjectionProvider(
- OrderedConfiguration<InjectionProvider> configuration)
+ public static void contributeTranslatorDefaultSource(
+ MappedConfiguration<Class, Translator> configuration)
{
- configuration.add("ComponentResources", new ComponentResourcesInjectionProvider());
- configuration.add("CommonResources", new CommonResourcesInjectionProvider());
- configuration.add("Default", new DefaultInjectionProvider(), "after:*.*");
+ configuration.add(Integer.class, new IntegerTranslator());
+ configuration.add(String.class, new StringTranslator());
+ configuration.add(Long.class, new LongTranslator());
+ configuration.add(Double.class, new DoubleTranslator());
}
/**
- * Adds a number of standard component class transform workers:
+ * Contributes the basic set of named translators:
* <ul>
- * <li>Retain -- allows fields to retain their values between requests</li>
- * <li>Persist -- allows fields to store their their value persistently between requests</li>
- * <li>Parameter -- identifies parameters based on the
- * {@link org.apache.tapestry.annotations.Parameter} annotation</li>
- * <li>Component -- identifies embedded components based on the
- * {@link org.apache.tapestry.annotations.Component} annotation</li>
- * <li>Mixin -- adds a mixin as part of a component's implementation</li>
- * <li>Environment -- allows fields to contain values extracted from the {@link Environment}
- * service</li>
- * <li>InjectNamed -- used with the {@link Inject} annotation, when a value is supplied</li>
- * <li>InjectAnnonymous -- used with the {@link Inject} annotation, when no value is supplied</li>
- * <li>InjectPage -- adds code to allow access to other pages via the {@link InjectPage} field
- * annotation</li>
- * <li>InjectBlock -- allows a block from the template to be injected into a field</li>
- * <li>SupportsInformalParameters -- checks for the annotation</li>
- * <li>Meta -- checks for meta data and adds it to the component model
- * <li>ApplicationState -- converts fields that reference application state objects
- * <li>UnclaimedField -- identifies unclaimed fields and resets them to null/0/false at the end
- * of the request</li>
- * <li>RenderCommand -- ensures all components also implement {@link RenderCommand}</li>
- * <li>SetupRender, BeginRender, etc. -- correspond to component render phases and annotations</li>
+ * <li>integer</li>
+ * <li>string</li>
+ * <li>long</li>
+ * <li>double</li>
* </ul>
*/
- public static void contributeComponentClassTransformWorker(
- OrderedConfiguration<ComponentClassTransformWorker> configuration,
-
- ServiceLocator locator,
-
- @InjectService("MasterObjectProvider")
- ObjectProvider objectProvider,
-
- @InjectService("InjectionProvider")
- InjectionProvider injectionProvider,
-
- @Inject("infrastructure:Environment")
- Environment environment,
-
- @Inject("infrastructure:ComponentClassResolver")
- ComponentClassResolver resolver,
-
- @InjectService("RequestPageCache")
- RequestPageCache requestPageCache,
-
- @Inject("infrastructure:AssetSource")
- AssetSource assetSource,
-
- @InjectService("SymbolSource")
- SymbolSource symbolSource,
+ public static void contributeTranslatorSource(
+ MappedConfiguration<String, Translator> configuration)
+ {
+ // Fortunately, the translators are tiny, so we don't have to worry about the slight
+ // duplication between this and TranslatorDefaultSource, though it is a pain to keep the two
+ // organized (perhaps they should be joined together into a single service, where we
+ // identify a name and a match type).
- @Inject("infrastructure:BindingSource")
- BindingSource bindingsource,
+ configuration.add("integer", new IntegerTranslator());
+ configuration.add("string", new StringTranslator());
+ configuration.add("long", new LongTranslator());
+ configuration.add("double", new DoubleTranslator());
+ }
- @Inject("infrastructure:ApplicationStateManager")
- ApplicationStateManager applicationStateManager)
+ /**
+ * Adds coercions:
+ * <ul>
+ * <li>String to {@link SelectModel}
+ * <li>Map to {@link SelectModel}
+ * <li>List to {@link GridDataSource}
+ * <li>null to {@link GridDataSource}
+ * <li>String to {@link GridPagerPosition}
+ * <li>List to {@link SelectModel}
+ * </ul>
+ */
+ public static void contributeTypeCoercer(Configuration<CoercionTuple> configuration)
{
- // TODO: Proper scheduling of all of this. Since a given field or method should
- // only have a single annotation, the order doesn't matter so much, as long as
- // UnclaimedField is last.
-
- configuration.add("Meta", new MetaWorker());
- configuration.add("ApplicationState", new ApplicationStateWorker(applicationStateManager));
- configuration.add("InjectNamed", new InjectNamedWorker(objectProvider, locator));
- configuration.add(
- "InjectAnonymous",
- new InjectAnonymousWorker(locator, injectionProvider),
- "after:InjectNamed");
- configuration.add(
- "InjectAsset",
- new InjectAssetWorker(assetSource, symbolSource),
- "before:InjectNamed");
- configuration.add("InjectBlock", new InjectBlockWorker(), "before:InjectNamed");
+ add(configuration, String.class, SelectModel.class, new Coercion<String, SelectModel>()
+ {
+ public SelectModel coerce(String input)
+ {
+ return TapestryInternalUtils.toSelectModel(input);
+ }
+ });
- configuration.add("MixinAfter", new MixinAfterWorker());
- configuration.add("Component", new ComponentWorker(resolver));
- configuration.add("Environment", new EnvironmentalWorker(environment));
- configuration.add("Mixin", new MixinWorker(resolver));
- configuration.add("OnEvent", new OnEventWorker());
- configuration.add("SupportsInformalParameters", new SupportsInformalParametersWorker());
- configuration.add("InjectPage", new InjectPageWorker(requestPageCache));
- configuration.add("InjectComponent", new InjectComponentWorker());
- configuration.add("RenderCommand", new RenderCommandWorker());
+ add(configuration, Map.class, SelectModel.class, new Coercion<Map, SelectModel>()
+ {
+ @SuppressWarnings("unchecked")
+ public SelectModel coerce(Map input)
+ {
+ return TapestryInternalUtils.toSelectModel(input);
+ }
+ });
- // Default values for parameters are often some form of injection, so make sure
- // that Parameter fields are processed after injections.
+ add(configuration, List.class, GridDataSource.class, new Coercion<List, GridDataSource>()
+ {
+ public GridDataSource coerce(List input)
+ {
+ return new ListGridDataSource(input);
+ }
+ });
- configuration.add("Parameter", new ParameterWorker(bindingsource), "after:Inject*");
+ add(configuration, void.class, GridDataSource.class, new Coercion<Void, GridDataSource>()
+ {
+ private final GridDataSource _source = new NullDataSource();
- // Workers for the component rendering state machine methods; this is in typical
- // execution order.
+ public GridDataSource coerce(Void input)
+ {
+ return _source;
+ }
+ });
- add(configuration, TransformConstants.SETUP_RENDER_SIGNATURE, SetupRender.class, false);
- add(configuration, TransformConstants.BEGIN_RENDER_SIGNATURE, BeginRender.class, false);
- add(
- configuration,
- TransformConstants.BEFORE_RENDER_TEMPLATE_SIGNATURE,
- BeforeRenderTemplate.class,
- false);
add(
configuration,
- TransformConstants.BEFORE_RENDER_BODY_SIGNATURE,
- BeforeRenderBody.class,
- false);
-
- // These phases operate in reverse order.
+ String.class,
+ GridPagerPosition.class,
+ new StringToEnumCoercion<GridPagerPosition>(GridPagerPosition.class));
- add(
- configuration,
- TransformConstants.AFTER_RENDER_BODY_SIGNATURE,
- AfterRenderBody.class,
- true);
- add(
- configuration,
- TransformConstants.AFTER_RENDER_TEMPLATE_SIGNATURE,
- AfterRenderTemplate.class,
- true);
- add(configuration, TransformConstants.AFTER_RENDER_SIGNATURE, AfterRender.class, true);
- add(configuration, TransformConstants.CLEANUP_RENDER_SIGNATURE, CleanupRender.class, true);
+ add(configuration, List.class, SelectModel.class, new Coercion<List, SelectModel>()
+ {
+ @SuppressWarnings("unchecked")
+ public SelectModel coerce(List input)
+ {
+ return TapestryInternalUtils.toSelectModel(input);
+ }
+ });
+ }
- // Ideally, these should be ordered pretty late in the process to make sure there are no
- // side effects
- // with other workers that do work inside the page lifecycle methods.
+ /**
+ * Adds built-in constraint generators:
+ * <ul>
+ * <li>PrimtiveField -- primitive fields are always required
+ * <li>ValidateAnnotation -- adds constraints from a {@link Validate} annotation
+ * </ul>
+ */
+ public static void contributeValidationConstraintGenerator(
+ OrderedConfiguration<ValidationConstraintGenerator> configuration)
+ {
+ configuration.add("PrimitiveField", new PrimitiveFieldConstraintGenerator());
+ configuration.add("ValidateAnnotation", new ValidateAnnotationConstraintGenerator());
+ }
- add(
- configuration,
- PageLoaded.class,
- TransformConstants.CONTAINING_PAGE_DID_LOAD_SIGNATURE,
- "pageLoaded");
- add(
- configuration,
- PageAttached.class,
- TransformConstants.CONTAINING_PAGE_DID_ATTACH_SIGNATURE,
- "pageAttached");
- add(
- configuration,
- PageDetached.class,
- TransformConstants.CONTAINING_PAGE_DID_DETACH_SIGNATURE,
- "pageDetached");
+ private static <S, T> void add(Configuration<CoercionTuple> configuration, Class<S> sourceType,
+ Class<T> targetType, Coercion<S, T> coercion)
+ {
+ CoercionTuple<S, T> tuple = new CoercionTuple<S, T>(sourceType, targetType, coercion);
- configuration.add("Retain", new RetainWorker());
- configuration.add("Persist", new PersistWorker());
- configuration.add("UnclaimedField", new UnclaimedFieldWorker(), "after:*.*");
+ configuration.add(tuple);
}
- private static void add(OrderedConfiguration<ComponentClassTransformWorker> configuration,
- MethodSignature signature, Class<? extends Annotation> annotationClass, boolean reverse)
+ /**
+ * Invoked from
+ * {@link #contributeInfrastructure(Configuration, ServiceLocator, Request, Response, TypeCoercer)}
+ * to contribute services from the tapestry module where the unqualified class name of the
+ * service interface matches the unqualified service id. This unqualified name is used as the
+ * infrastructure alias.
+ */
+ @SuppressWarnings("unchecked")
+ private static void add(Configuration<InfrastructureContribution> configuration,
+ ServiceLocator locator, Class... serviceInterfaces)
{
- // make the name match the annotation class name.
+ for (Class serviceInterface : serviceInterfaces)
+ {
+ String serviceId = TapestryInternalUtils.lastTerm(serviceInterface.getName());
- String name = TapestryInternalUtils.lastTerm(annotationClass.getName());
+ Object service = locator.getService(serviceId, serviceInterface);
- configuration.add(name, new ComponentLifecycleMethodWorker(signature, annotationClass,
- reverse));
+ InfrastructureContribution contribution = new InfrastructureContribution(serviceId,
+ service);
+
+ configuration.add(contribution);
+ }
}
private static void add(OrderedConfiguration<ComponentClassTransformWorker> configuration,
@@ -937,148 +916,132 @@
configuration.add(name, worker);
}
- @Lifecycle("perthread")
- public static Environment buildEnvironment()
+ private static void add(OrderedConfiguration<ComponentClassTransformWorker> configuration,
+ MethodSignature signature, Class<? extends Annotation> annotationClass, boolean reverse)
{
- return new EnvironmentImpl();
+ // make the name match the annotation class name.
+
+ String name = TapestryInternalUtils.lastTerm(annotationClass.getName());
+
+ configuration.add(name, new ComponentLifecycleMethodWorker(signature, annotationClass,
+ reverse));
}
- /**
- * Controls setup and cleanup of the environment during page rendering (the generation of a
- * markup stream response for the client web browser).
- */
- public PageRenderInitializer buildPageRenderInitializer(
- final List<PageRenderCommand> configuration)
- {
- return new PageRenderInitializer()
- {
- public void setup(MarkupWriter writer)
- {
- _environment.clear();
+ private final ChainBuilder _chainBuilder;
- _environment.push(MarkupWriter.class, writer);
- _environment.push(Document.class, writer.getDocument());
+ private final PipelineBuilder _pipelineBuilder;
- for (PageRenderCommand command : configuration)
- command.setup(_environment);
- }
+ private final RequestGlobals _requestGlobals;
- public void cleanup(MarkupWriter writer)
- {
- Iterator<PageRenderCommand> i = InternalUtils.reverseIterator(configuration);
+ private final ApplicationGlobals _applicationGlobals;
- while (i.hasNext())
- i.next().cleanup(_environment);
+ private final PropertyShadowBuilder _shadowBuilder;
- _environment.clear();
- }
- };
- }
+ private final RequestPageCache _requestPageCache;
- public void contributePageRenderInitializer(
- OrderedConfiguration<PageRenderCommand> configuration,
+ private final PageResponseRenderer _pageResponseRenderer;
- @InjectService("ThreadLocale")
- ThreadLocale threadLocale,
+ private final Request _request;
- @Inject("infrastructure:AssetSource")
- AssetSource assetSource,
+ private final Environment _environment;
- @Inject("infrastructure:ValidationMessagesSource")
- ValidationMessagesSource validationMessagesSource,
+ private final StrategyBuilder _strategyBuilder;
- @Inject("service:SymbolSource")
- final SymbolSource symbolSource,
+ private final ComponentInstantiatorSource _componentInstantiatorSource;
+
+ private final LinkFactory _linkFactory;
+
+ private final PropertyAccess _propertyAccess;
+
+ private final PropertyConduitSource _propertyConduitSource;
+
+ private final ClassFactory _componentClassFactory;
+
+ public TapestryModule(@InjectService("PipelineBuilder")
+ PipelineBuilder pipelineBuilder,
+
+ @InjectService("PropertyShadowBuilder")
+ PropertyShadowBuilder shadowBuilder,
- @Inject("service:ClasspathAssetFactory")
- final AssetFactory classpathAssetFactory)
- {
- configuration.add("PageRenderSupport", new PageRenderCommand()
- {
- public void setup(Environment environment)
- {
- DocumentScriptBuilder builder = new DocumentScriptBuilderImpl();
+ @Inject("infrastructure:RequestGlobals")
+ RequestGlobals requestGlobals,
- environment.push(DocumentScriptBuilder.class, builder);
- environment.push(PageRenderSupport.class, new PageRenderSupportImpl(builder,
- symbolSource, classpathAssetFactory));
- }
+ @Inject("infrastructure:ApplicationGlobals")
+ ApplicationGlobals applicationGlobals,
- public void cleanup(Environment environment)
- {
- environment.pop(PageRenderSupport.class);
+ @InjectService("ChainBuilder")
+ ChainBuilder chainBuilder,
- Document document = environment.peek(Document.class);
+ @InjectService("RequestPageCache")
+ RequestPageCache requestPageCache,
- DocumentScriptBuilder builder = environment.pop(DocumentScriptBuilder.class);
+ @InjectService("PageResponseRenderer")
+ PageResponseRenderer pageResponseRenderer,
- builder.updateDocument(document);
- }
- });
+ @Inject("infrastructure:Request")
+ Request request,
- configuration.add("Heartbeat", new PageRenderCommand()
- {
- public void setup(Environment environment)
- {
- HeartbeatImpl heartbeat = new HeartbeatImpl();
+ @Inject("infrastructure:Environment")
+ Environment environment,
- heartbeat.begin();
+ @InjectService("StrategyBuilder")
+ StrategyBuilder strategyBuilder,
- environment.push(Heartbeat.class, heartbeat);
- }
+ @InjectService("ComponentInstantiatorSource")
+ ComponentInstantiatorSource componentInstantiatorSource,
- public void cleanup(Environment environment)
- {
- environment.pop(Heartbeat.class).end();
- }
- });
+ @InjectService("LinkFactory")
+ LinkFactory linkFactory,
- configuration.add("InjectStandardStylesheet", new InjectStandardStylesheetCommand(
- threadLocale, assetSource));
+ @Inject("infrastructure:PropertyConduitSource")
+ PropertyConduitSource propertyConduitSource,
- Asset iconAsset = assetSource.getClasspathAsset(
- "org/apache/tapestry/field-error-marker.png",
- Locale.ENGLISH);
+ @Inject("infrastructure:PropertyAccess")
+ PropertyAccess propertyAccess,
- configuration.add("DefaultValidationDelegate", new DefaultValidationDelegateCommand(
- threadLocale, validationMessagesSource, iconAsset));
+ @InjectService("ComponentClassFactory")
+ ClassFactory componentClassFactory)
+ {
+ _pipelineBuilder = pipelineBuilder;
+ _shadowBuilder = shadowBuilder;
+ _requestGlobals = requestGlobals;
+ _applicationGlobals = applicationGlobals;
+ _chainBuilder = chainBuilder;
+ _requestPageCache = requestPageCache;
+ _pageResponseRenderer = pageResponseRenderer;
+ _request = request;
+ _environment = environment;
+ _strategyBuilder = strategyBuilder;
+ _componentInstantiatorSource = componentInstantiatorSource;
+ _linkFactory = linkFactory;
+ _propertyAccess = propertyAccess;
+ _propertyConduitSource = propertyConduitSource;
+ _componentClassFactory = componentClassFactory;
}
- /** A public service since extensions may provide new persistent strategies. */
- public static PersistentFieldManager buildPersistentFieldManager(
- @Inject("infrastructure:MetaDataLocator")
- MetaDataLocator locator,
-
- Map<String, PersistentFieldStrategy> configuration)
+ public Context build(@InjectService("ApplicationGlobals")
+ ApplicationGlobals globals)
{
- return new PersistentFieldManagerImpl(locator, configuration);
+ return _shadowBuilder.build(globals, "context", Context.class);
}
/**
- * Contributes the "session" strategy.
+ * A service for building proxies that shadow a value stored in the {@link Environment}.
*/
- public void contributePersistentFieldManager(
- MappedConfiguration<String, PersistentFieldStrategy> configuration,
-
- @InjectService("SessionHolder")
- SessionHolder sessionHolder)
+ public EnvironmentalShadowBuilder build(@Inject("service:ClassFactory")
+ ClassFactory classFactory)
{
- configuration.add("session", new SessionPersistentFieldStrategy(sessionHolder));
- configuration.add("flash", new FlashPersistentFieldStrategy(sessionHolder));
+ return new EnvironmentalShadowBuilderImpl(classFactory, _environment);
}
- public ComponentSource buildComponentSource(@InjectService("RequestPageCache")
- RequestPageCache pageCache)
+ public ComponentClassResolver build(Collection<LibraryMapping> configuration)
{
- return new ComponentSourceImpl(pageCache);
- }
+ ComponentClassResolverImpl service = new ComponentClassResolverImpl(
+ _componentInstantiatorSource, new ComponentClassLocatorImpl(), configuration);
- public ComponentMessagesSource buildComponentMessagesSource(@InjectService("UpdateListenerHub")
- UpdateListenerHub updateListenerHub)
- {
- ComponentMessagesSourceImpl service = new ComponentMessagesSourceImpl();
+ // Allow the resolver to clean its cache when the source is invalidated
- updateListenerHub.addUpdateListener(service);
+ _componentInstantiatorSource.addInvalidationListener(service);
return service;
}
@@ -1088,7 +1051,7 @@
* paths to message bundles (resource paths within the classpath); the default contribution is
* "org/apache/tapestry/internal/ValidationMessages".
*/
- public ValidationMessagesSource buildValidationMessagesSource(Collection<String> configuration,
+ public ValidationMessagesSource build(Collection<String> configuration,
@InjectService("UpdateListenerHub")
UpdateListenerHub updateListenerHub,
@@ -1103,214 +1066,173 @@
return service;
}
- public void contributeValidationMessagesSource(Configuration<String> configuration)
- {
- configuration.add("org/apache/tapestry/internal/ValidationMessages");
- }
-
- public static AssetSource buildAssetSource(Map<String, AssetFactory> configuration)
- {
- return new AssetSourceImpl(configuration);
- }
-
- public void contributeAssetSource(MappedConfiguration<String, AssetFactory> configuration,
- @InjectService("ContextAssetFactory")
- AssetFactory contextAssetFactory,
-
- @InjectService("ClasspathAssetFactory")
- AssetFactory classpathAssetFactory)
- {
- configuration.add("context", contextAssetFactory);
- configuration.add("classpath", classpathAssetFactory);
- }
-
- public static ResourceDigestGenerator buildResourceDigestGenerator()
- {
- return new ResourceDigestGeneratorImpl();
- }
-
- public static ClasspathAssetAliasManager buildClasspathAssetAliasManager(
- @InjectService("ContextPathSource")
- ContextPathSource contextPathSource, Map<String, String> configuration)
- {
- return new ClasspathAssetAliasManagerImpl(contextPathSource, configuration);
- }
-
- public static void contributeClasspathAssetAliasManager(
- MappedConfiguration<String, String> configuration,
+ public MetaDataLocator build(@Inject("infrastructure:ComponentClassResolver")
+ ComponentClassResolver componentClassResolver,
- @Inject("${tapestry.scriptaculous.path}")
- String scriptaculousPath)
+ Map<String, String> configuration)
{
- configuration.add("tapestry/", "org/apache/tapestry/");
-
- configuration.add("scriptaculous/", scriptaculousPath + "/");
- }
-
- public static FieldValidatorSource buildFieldValidatorSource(
- @Inject("infrastructure:ValidationMessagesSource")
- ValidationMessagesSource messagesSource,
-
- @Inject("infrastructure:TypeCoercer")
- TypeCoercer typeCoercer,
+ MetaDataLocatorImpl service = new MetaDataLocatorImpl(componentClassResolver, configuration);
- @Inject("service:PageRenderSupport")
- PageRenderSupport pageRenderSupport,
+ _componentInstantiatorSource.addInvalidationListener(service);
- Map<String, Validator> configuration)
- {
- return new FieldValidatorSourceImpl(messagesSource, typeCoercer, pageRenderSupport,
- configuration);
+ return service;
}
/**
- * Contributes the basic set of validators:
- * <ul>
- * <li>required</li>
- * <li>minlength</li>
- * <li>maxlength</li>
- * <li>min</li>
- * <li>max</li>
- * </ul>
+ * Builds a proxy to the current PageRenderSupport inside this thread's {@link Environment}.
*/
- public static void contributeFieldValidatorSource(
- MappedConfiguration<String, Validator> configuration)
+ public PageRenderSupport build(@Inject("service:EnvironmentalShadowBuilder")
+ EnvironmentalShadowBuilder builder)
{
- configuration.add("required", new Required());
- configuration.add("minlength", new MinLength());
- configuration.add("maxlength", new MaxLength());
- configuration.add("min", new Min());
- configuration.add("max", new Max());
+ return builder.build(PageRenderSupport.class);
}
- public static TranslatorSource buildTranslatorSource(Map<String, Translator> configuration)
+ /**
+ * Allows the exact steps in the component class transformation process to be defined.
+ */
+ public ComponentClassTransformWorker build(List<ComponentClassTransformWorker> configuration)
{
- return new TranslatorSourceImpl(configuration);
+ return _chainBuilder.build(ComponentClassTransformWorker.class, configuration);
}
- public TranslatorDefaultSource buildTranslatorDefaultSource(Map<Class, Translator> configuration)
+ public DataTypeAnalyzer build(List<DataTypeAnalyzer> configuration)
{
- TranslatorDefaultSourceImpl service = new TranslatorDefaultSourceImpl(configuration);
-
- _componentInstantiatorSource.addInvalidationListener(service);
-
- return service;
+ return _chainBuilder.build(DataTypeAnalyzer.class, configuration);
}
/**
- * Contributes the basic set of named translators:
- * <ul>
- * <li>integer</li>
- * <li>string</li>
- * <li>long</li>
- * <li>double</li>
- * </ul>
+ * A chain of command for providing values for {@link org.apache.tapestry.annotations.Inject}-ed
+ * fields in component classes. The service's configuration can be extended to allow for
+ * different automatic injections (based on some combination of field type and field name).
*/
- public static void contributeTranslatorSource(
- MappedConfiguration<String, Translator> configuration)
- {
- // Fortunately, the translators are tiny, so we don't have to worry about the slight
- // duplication between this and TranslatorDefaultSource, though it is a pain to keep the two
- // organized (perhaps they should be joined together into a single service, where we
- // identify a name and a match type).
-
- configuration.add("integer", new IntegerTranslator());
- configuration.add("string", new StringTranslator());
- configuration.add("long", new LongTranslator());
- configuration.add("double", new DoubleTranslator());
- }
- /**
- * Contributes the basic set of default translators:
- * <ul>
- * <li>Integer</li>
- * <li>String</li>
- * <li>Long</li>
- * <li>Double</li>
- * </li>
- */
- public static void contributeTranslatorDefaultSource(
- MappedConfiguration<Class, Translator> configuration)
+ public InjectionProvider build(List<InjectionProvider> configuration)
{
- configuration.add(Integer.class, new IntegerTranslator());
- configuration.add(String.class, new StringTranslator());
- configuration.add(Long.class, new LongTranslator());
- configuration.add(Double.class, new DoubleTranslator());
+ return _chainBuilder.build(InjectionProvider.class, configuration);
}
/**
- * Adds coercions:
- * <ul>
- * <li>String to {@link SelectModel}
- * <li>Map to {@link SelectModel}
- * <li>List to {@link GridDataSource}
- * <li>null to {@link GridDataSource}
- * <li>String to {@link GridPagerPosition}
- * <li>List to {@link SelectModel}
- * </ul>
+ * Controls setup and cleanup of the environment during page rendering (the generation of a
+ * markup stream response for the client web browser).
*/
- public static void contributeTypeCoercer(Configuration<CoercionTuple> configuration)
+ public PageRenderInitializer build(final List<PageRenderCommand> configuration)
{
- add(configuration, String.class, SelectModel.class, new Coercion<String, SelectModel>()
+ return new PageRenderInitializer()
{
- public SelectModel coerce(String input)
+ public void cleanup(MarkupWriter writer)
{
- return TapestryInternalUtils.toSelectModel(input);
+ Iterator<PageRenderCommand> i = InternalUtils.reverseIterator(configuration);
+
+ while (i.hasNext())
+ i.next().cleanup(_environment);
+
+ _environment.clear();
}
- });
- add(configuration, Map.class, SelectModel.class, new Coercion<Map, SelectModel>()
- {
- @SuppressWarnings("unchecked")
- public SelectModel coerce(Map input)
+ public void setup(MarkupWriter writer)
{
- return TapestryInternalUtils.toSelectModel(input);
+ _environment.clear();
+
+ _environment.push(MarkupWriter.class, writer);
+ _environment.push(Document.class, writer.getDocument());
+
+ for (PageRenderCommand command : configuration)
+ command.setup(_environment);
}
- });
+ };
+ }
- add(configuration, List.class, GridDataSource.class, new Coercion<List, GridDataSource>()
+ /** Initializes the application. */
+ public ApplicationInitializer build(Log log, List<ApplicationInitializerFilter> configuration)
+ {
+ ApplicationInitializer terminator = new ApplicationInitializer()
{
- public GridDataSource coerce(List input)
+ public void initializeApplication(Context context)
{
- return new ListGridDataSource(input);
+ _applicationGlobals.store(context);
}
- });
+ };
- add(configuration, void.class, GridDataSource.class, new Coercion<Void, GridDataSource>()
- {
- private final GridDataSource _source = new NullDataSource();
+ return _pipelineBuilder.build(
+ log,
+ ApplicationInitializer.class,
+ ApplicationInitializerFilter.class,
+ configuration,
+ terminator);
+ }
- public GridDataSource coerce(Void input)
+ public HttpServletRequestHandler build(Log log, List<HttpServletRequestFilter> configuration,
+
+ @InjectService("RequestHandler")
+ final RequestHandler handler)
+ {
+ HttpServletRequestHandler terminator = new HttpServletRequestHandler()
+ {
+ public boolean service(HttpServletRequest request, HttpServletResponse response)
+ throws IOException
{
- return _source;
+ _requestGlobals.store(request, response);
+
+ return handler.service(new RequestImpl(request), new ResponseImpl(response));
}
- });
+ };
- add(
+ return _pipelineBuilder.build(
+ log,
+ HttpServletRequestHandler.class,
+ HttpServletRequestFilter.class,
configuration,
- String.class,
- GridPagerPosition.class,
- new StringToEnumCoercion<GridPagerPosition>(GridPagerPosition.class));
+ terminator);
+ }
- add(configuration, List.class, SelectModel.class, new Coercion<List, SelectModel>()
+ public RequestHandler build(Log log, List<RequestFilter> configuration,
+ @InjectService("MasterDispatcher")
+ final Dispatcher masterDispatcher)
+ {
+ RequestHandler terminator = new RequestHandler()
{
- @SuppressWarnings("unchecked")
- public SelectModel coerce(List input)
+ public boolean service(Request request, Response response) throws IOException
{
- return TapestryInternalUtils.toSelectModel(input);
+ _requestGlobals.store(request, response);
+
+ return masterDispatcher.dispatch(request, response);
}
- });
+ };
+
+ return _pipelineBuilder.build(
+ log,
+ RequestHandler.class,
+ RequestFilter.class,
+ configuration,
+ terminator);
}
- private static <S, T> void add(Configuration<CoercionTuple> configuration, Class<S> sourceType,
- Class<T> targetType, Coercion<S, T> coercion)
+ public ServletApplicationInitializer build(Log log,
+ List<ServletApplicationInitializerFilter> configuration,
+ @InjectService("ApplicationInitializer")
+ final ApplicationInitializer initializer)
{
- CoercionTuple<S, T> tuple = new CoercionTuple<S, T>(sourceType, targetType, coercion);
+ ServletApplicationInitializer terminator = new ServletApplicationInitializer()
+ {
+ public void initializeApplication(ServletContext context)
+ {
+ _applicationGlobals.store(context);
- configuration.add(tuple);
+ // And now, down the (Web) ApplicationInitializer pipeline ...
+
+ initializer.initializeApplication(new ContextImpl(context));
+ }
+ };
+
+ return _pipelineBuilder.build(
+ log,
+ ServletApplicationInitializer.class,
+ ServletApplicationInitializerFilter.class,
+ configuration,
+ terminator);
}
- public ComponentEventResultProcessor buildComponentEventResultProcessor(
+ public ComponentEventResultProcessor build(
Map<Class, ComponentEventResultProcessor> configuration)
{
// A slight hack!
@@ -1326,109 +1248,49 @@
}
/**
- * Contributes handlers for the following types:
- * <dl>
- * <dt>Object</dt>
- * <dd>Failure case, added to provide a more useful exception message</dd>
- * <dt>ActionResponseGenerator</dt>
- * <dd>Returns the ActionResponseGenerator; this sometimes occurs when a component generates
- * events whose return values are converted to ActionResponseGenerators (this handles that
- * bubble up case).</dd>
- * <dt>Link</dt>
- * <dd>Wraps the Link to send a redirect</dd>
- * <dt>String</dt>
- * <dd>The name of the page to render the response (after a redirect)</dd>
- * </dl>
+ * The default data type analyzer is the final analyzer consulted and identifies the type
+ * entirely pased on the property type, working against its own configuration (mapping property
+ * type class to data type).
*/
- public void contributeComponentEventResultProcessor(
- @InjectService("ComponentInstanceResultProcessor")
- ComponentEventResultProcessor componentInstanceProcessor,
-
- MappedConfiguration<Class, ComponentEventResultProcessor> configuration)
+ public DataTypeAnalyzer buildDefaultDataTypeAnalyzer(Map<Class, String> configuration)
{
- configuration.add(
- ActionResponseGenerator.class,
- new ComponentEventResultProcessor<ActionResponseGenerator>()
- {
- public ActionResponseGenerator processComponentEvent(
- ActionResponseGenerator value, Component component,
- String methodDescripion)
- {
- return value;
- }
- });
-
- configuration.add(Link.class, new ComponentEventResultProcessor<Link>()
- {
-
- public ActionResponseGenerator processComponentEvent(Link value, Component component,
- String methodDescripion)
- {
- return new LinkActionResponseGenerator(value);
- }
- });
-
- configuration.add(String.class, new StringResultProcessor(_requestPageCache, _linkFactory));
-
- configuration.add(Component.class, componentInstanceProcessor);
+ DefaultDataTypeAnalyzer service = new DefaultDataTypeAnalyzer(configuration);
- configuration.add(StreamResponse.class, new StreamResponseResultProcessor());
- }
+ _componentInstantiatorSource.addInvalidationListener(service);
- public ComponentEventResultProcessor buildComponentInstanceResultProcessor(Log log)
- {
- return new ComponentInstanceResultProcessor(_requestPageCache, _linkFactory, log);
+ return service;
}
- public static PersistentLocale buildPersistentLocale(@InjectService("Cookies")
- Cookies cookies)
+ public TranslatorDefaultSource build(Map<Class, Translator> configuration)
{
- return new PersistentLocaleImpl(cookies);
- }
-
- public static Cookies buildCookies(@InjectService("ContextPathSource")
- ContextPathSource contextPathSource,
-
- @InjectService("CookieSource")
- CookieSource cookieSource,
+ TranslatorDefaultSourceImpl service = new TranslatorDefaultSourceImpl(configuration);
- @InjectService("CookieSink")
- CookieSink cookieSink,
+ _componentInstantiatorSource.addInvalidationListener(service);
- @Inject("${tapestry.default-cookie-max-age}")
- int defaultMaxAge)
- {
- return new CookiesImpl(contextPathSource, cookieSource, cookieSink, defaultMaxAge);
+ return service;
}
- public static ApplicationStatePersistenceStrategySource buildApplicationStatePersistenceStrategySource(
- Map<String, ApplicationStatePersistenceStrategy> configuration)
+ public ComponentSource build(@InjectService("RequestPageCache")
+ RequestPageCache pageCache)
{
- return new ApplicationStatePersistenceStrategySourceImpl(configuration);
+ return new ComponentSourceImpl(pageCache);
}
- /** Contributes the default "session" strategy. */
- public void contributeApplicationStatePersistenceStrategySource(
- MappedConfiguration<String, ApplicationStatePersistenceStrategy> configuration)
+ public ObjectRenderer build(@InjectService("StrategyBuilder")
+ StrategyBuilder strategyBuilder, Map<Class, ObjectRenderer> configuration)
{
- configuration.add("session", new SessionApplicationStatePersistenceStrategy(_request));
- }
+ StrategyRegistry<ObjectRenderer> registry = StrategyRegistry.newInstance(
+ ObjectRenderer.class,
+ configuration);
- public static ApplicationStateManager buildApplicationStateManager(
- Map<Class, ApplicationStateContribution> configuration,
- @Inject("infrastructure:ApplicationStatePersistenceStrategySource")
- ApplicationStatePersistenceStrategySource source)
- {
- return new ApplicationStateManagerImpl(configuration, source);
+ return _strategyBuilder.build(registry);
}
/**
* The configuration of the model source is a mapping from type to string. The types are
* property types and the values, the strings, represent different type of editors.
*/
- public BeanModelSource buildBeanModelSource(
-
- @Inject("infrastructure:TypeCoercer")
+ public BeanModelSource build(@Inject("infrastructure:TypeCoercer")
TypeCoercer typeCoercer,
@InjectService("DataTypeAnalyzer")
@@ -1438,94 +1300,51 @@
_componentClassFactory, analyzer);
}
- public DataTypeAnalyzer buildDataTypeAnalyzer(List<DataTypeAnalyzer> configuration)
- {
- return _chainBuilder.build(DataTypeAnalyzer.class, configuration);
- }
-
- /**
- * Adds the {@link #buildDefaultDataTypeAnalyzer(Map) DefaultDatatTypeAnalyzer} to the
- * configuration, ordered explicitly last.
- */
- public static void contributeDataTypeAnalyzer(
- OrderedConfiguration<DataTypeAnalyzer> configuration,
- @InjectService("DefaultDataTypeAnalyzer")
- DataTypeAnalyzer defaultDataTypeAnalyzer)
- {
- configuration.add("Default", defaultDataTypeAnalyzer, "after:*");
- }
-
- /**
- * The default data type analyzer is the final analyzer consulted and identifies the type
- * entirely pased on the property type, working against its own configuration (mapping property
- * type class to data type).
- */
- public DataTypeAnalyzer buildDefaultDataTypeAnalyzer(Map<Class, String> configuration)
+ public ComponentMessagesSource build(@InjectService("UpdateListenerHub")
+ UpdateListenerHub updateListenerHub)
{
- DefaultDataTypeAnalyzer service = new DefaultDataTypeAnalyzer(configuration);
+ ComponentMessagesSourceImpl service = new ComponentMessagesSourceImpl();
- _componentInstantiatorSource.addInvalidationListener(service);
+ updateListenerHub.addUpdateListener(service);
return service;
}
/**
- * Maps property types to data type names
- * <ul>
- * <li>String --> text
- * <li>Number --> text
- * <li>Enum --> enum
- * <li>Boolean --> checkbox
- * </ul>
+ * Returns a {@link ClassFactory} that can be used to create extra classes around component
+ * classes. This ClassFactory will be cleared whenever an underlying component class is
+ * discovered to have changed. Use of this class factory implies that your code will become
+ * aware of this (if necessary) to discard any cached object (alas, this currently involves
+ * dipping into the internals side to register for the correct notifications). Failure to
+ * properly clean up can result in really nasty PermGen space memory leaks.
*/
- public static void contributeDefaultDataTypeAnalyzer(
- MappedConfiguration<Class, String> configuration)
+ public ClassFactory buildComponentClassFactory()
{
- // This is a special case contributed to avoid exceptions when a property type can't be
- // matched. DefaultDataTypeAnalyzer converts the empty string to null.
-
- configuration.add(Object.class, "");
-
- configuration.add(String.class, "text");
-
- // This may change; as currently implemented, "text" refers more to the edit component
- // (TextField) than to
- // the "flavor" of data.
+ return _shadowBuilder.build(
+ _componentInstantiatorSource,
+ "classFactory",
+ ClassFactory.class);
+ }
- configuration.add(Number.class, "text");
- configuration.add(Enum.class, "enum");
- configuration.add(Boolean.class, "checkbox");
+ public ComponentEventResultProcessor buildComponentInstanceResultProcessor(Log log)
+ {
+ return new ComponentInstanceResultProcessor(_requestPageCache, _linkFactory, log);
}
- public static ValidationConstraintGenerator buildValidationConstraintGenerator(
- List<ValidationConstraintGenerator> configuration)
+ public DefaultComponentParameterBindingSource buildDefaultComponentParameterBindingSource(
+ @Inject("infrastructure:BindingSource")
+ BindingSource bindingSource)
{
- return new ValidationConstraintGeneratorImpl(configuration);
+ return new DefaultComponentParameterBindingSourceImpl(_propertyAccess, bindingSource);
}
/**
- * Adds built-in constraint generators:
- * <ul>
- * <li>PrimtiveField -- primitive fields are always required
- * <li>ValidateAnnotation -- adds constraints from a {@link Validate} annotation
- * </ul>
+ * Ordered contributions to the MasterDispatcher service allow different URL matching strategies
+ * to occur.
*/
- public static void contributeValidationConstraintGenerator(
- OrderedConfiguration<ValidationConstraintGenerator> configuration)
- {
- configuration.add("PrimitiveField", new PrimitiveFieldConstraintGenerator());
- configuration.add("ValidateAnnotation", new ValidateAnnotationConstraintGenerator());
- }
-
- public static FieldValidatorDefaultSource buildFieldValidatorDefaultSource(
- @Inject("infrastructure:ValidationConstraintGenerator")
- ValidationConstraintGenerator validationConstraintGenerator,
-
- @Inject("infrastructure:FieldValidatorSource")
- FieldValidatorSource fieldValidatorSource)
+ public Dispatcher buildMasterDispatcher(List<Dispatcher> configuration)
{
- return new FieldValidatorDefaultSourceImpl(validationConstraintGenerator,
- fieldValidatorSource);
+ return _chainBuilder.build(Dispatcher.class, configuration);
}
public PropertyConduitSource buildPropertyConduitSource()
@@ -1538,40 +1357,141 @@
return service;
}
- public MetaDataLocator buildMetaDataLocator(@Inject("infrastructure:ComponentClassResolver")
- ComponentClassResolver componentClassResolver,
+ /**
+ * Builds a shadow of the RequestGlobals.request property. Note again that the shadow can be an
+ * ordinary singleton, even though RequestGlobals is perthread.
+ */
+ public Request buildRequest()
+ {
+ return _shadowBuilder.build(_requestGlobals, "request", Request.class);
+ }
- Map<String, String> configuration)
+ /**
+ * Builds a shadow of the RequestGlobals.response property. Note again that the shadow can be an
+ * ordinary singleton, even though RequestGlobals is perthread.
+ */
+ public Response buildResponse()
{
- MetaDataLocatorImpl service = new MetaDataLocatorImpl(componentClassResolver, configuration);
+ return _shadowBuilder.build(_requestGlobals, "response", Response.class);
+ }
- _componentInstantiatorSource.addInvalidationListener(service);
+ /** Contributes the default "session" strategy. */
+ public void contributeApplicationStatePersistenceStrategySource(
+ MappedConfiguration<String, ApplicationStatePersistenceStrategy> configuration)
+ {
+ configuration.add("session", new SessionApplicationStatePersistenceStrategy(_request));
+ }
- return service;
+ public void contributeAssetSource(MappedConfiguration<String, AssetFactory> configuration,
+ @InjectService("ContextAssetFactory")
+ AssetFactory contextAssetFactory,
+
+ @InjectService("ClasspathAssetFactory")
+ AssetFactory classpathAssetFactory)
+ {
+ configuration.add("context", contextAssetFactory);
+ configuration.add("classpath", classpathAssetFactory);
}
- public void contributeMetaDataLocator(MappedConfiguration<String, String> configuration)
+ /**
+ * Contributes handlers for the following types:
+ * <dl>
+ * <dt>Object</dt>
+ * <dd>Failure case, added to provide a more useful exception message</dd>
+ * <dt>ActionResponseGenerator</dt>
+ * <dd>Returns the ActionResponseGenerator; this sometimes occurs when a component generates
+ * events whose return values are converted to ActionResponseGenerators (this handles that
+ * bubble up case).</dd>
+ * <dt>Link</dt>
+ * <dd>Wraps the Link to send a redirect</dd>
+ * <dt>String</dt>
+ * <dd>The name of the page to render the response (after a redirect)</dd>
+ * </dl>
+ */
+ public void contributeComponentEventResultProcessor(
+ @InjectService("ComponentInstanceResultProcessor")
+ ComponentEventResultProcessor componentInstanceProcessor,
+
+ MappedConfiguration<Class, ComponentEventResultProcessor> configuration)
{
configuration.add(
- PersistentFieldManagerImpl.META_KEY,
- PersistentFieldManagerImpl.DEFAULT_STRATEGY);
+ ActionResponseGenerator.class,
+ new ComponentEventResultProcessor<ActionResponseGenerator>()
+ {
+ public ActionResponseGenerator processComponentEvent(
+ ActionResponseGenerator value, Component component,
+ String methodDescripion)
+ {
+ return value;
+ }
+ });
+
+ configuration.add(Link.class, new ComponentEventResultProcessor<Link>()
+ {
+
+ public ActionResponseGenerator processComponentEvent(Link value, Component component,
+ String methodDescripion)
+ {
+ return new LinkActionResponseGenerator(value);
+ }
+ });
+
+ configuration.add(String.class, new StringResultProcessor(_requestPageCache, _linkFactory));
+
+ configuration.add(Component.class, componentInstanceProcessor);
+
+ configuration.add(StreamResponse.class, new StreamResponseResultProcessor());
}
- public DefaultComponentParameterBindingSource buildDefaultComponentParameterBindingSource(
- @Inject("infrastructure:BindingSource")
- BindingSource bindingSource)
+ public void contributeMasterDispatcher(OrderedConfiguration<Dispatcher> configuration,
+ @Inject("infrastructure:ClasspathAssetAliasManager")
+ ClasspathAssetAliasManager aliasManager,
+
+ @InjectService("ResourceCache")
+ ResourceCache resourceCache,
+
+ @InjectService("ResourceStreamer")
+ ResourceStreamer streamer,
+
+ @InjectService("PageLinkHandler")
+ PageLinkHandler pageLinkHandler,
+
+ @InjectService("ActionLinkHandler")
+ ActionLinkHandler actionLinkHandler,
+
+ @InjectService("ComponentClassResolver")
+ ComponentClassResolver componentClassResolver,
+
+ @Inject("${tapestry.start-page-name}")
+ String startPageName)
{
- return new DefaultComponentParameterBindingSourceImpl(_propertyAccess, bindingSource);
+ // Looks for the root path and renders the start page
+
+ configuration.add("RootPath", new RootPathDispatcher(componentClassResolver,
+ pageLinkHandler, _pageResponseRenderer, startPageName), "before:Asset");
+
+ // This goes first because an asset to be streamed may have an file extension, such as
+ // ".html", that will confuse the later dispatchers.
+
+ configuration.add(
+ "Asset",
+ new AssetDispatcher(streamer, aliasManager, resourceCache),
+ "before:PageRender");
+
+ configuration.add("PageRender", new PageRenderDispatcher(componentClassResolver,
+ pageLinkHandler, _pageResponseRenderer));
+
+ configuration.add(
+ "ComponentAction",
+ new ComponentActionDispatcher(actionLinkHandler),
+ "after:PageRender");
}
- public ObjectRenderer buildObjectRenderer(@InjectService("StrategyBuilder")
- StrategyBuilder strategyBuilder, Map<Class, ObjectRenderer> configuration)
+ public void contributeMetaDataLocator(MappedConfiguration<String, String> configuration)
{
- StrategyRegistry<ObjectRenderer> registry = StrategyRegistry.newInstance(
- ObjectRenderer.class,
- configuration);
-
- return _strategyBuilder.build(registry);
+ configuration.add(
+ PersistentFieldManagerImpl.META_KEY,
+ PersistentFieldManagerImpl.DEFAULT_STRATEGY);
}
/**
[... 103 lines stripped ...]