001// Copyright 2008, 2009, 2010, 2011 The Apache Software Foundation
002//
003// Licensed under the Apache License, Version 2.0 (the "License");
004// you may not use this file except in compliance with the License.
005// You may obtain a copy of the License at
006//
007// http://www.apache.org/licenses/LICENSE-2.0
008//
009// Unless required by applicable law or agreed to in writing, software
010// distributed under the License is distributed on an "AS IS" BASIS,
011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012// See the License for the specific language governing permissions and
013// limitations under the License.
014
015package org.apache.tapestry5.internal.services;
016
017import org.apache.tapestry5.SymbolConstants;
018import org.apache.tapestry5.internal.pageload.PageLoaderImpl;
019import org.apache.tapestry5.internal.services.ajax.AjaxFormUpdateController;
020import org.apache.tapestry5.internal.services.javascript.JavaScriptStackPathConstructor;
021import org.apache.tapestry5.internal.structure.ComponentPageElementResourcesSource;
022import org.apache.tapestry5.internal.structure.ComponentPageElementResourcesSourceImpl;
023import org.apache.tapestry5.ioc.MappedConfiguration;
024import org.apache.tapestry5.ioc.ObjectLocator;
025import org.apache.tapestry5.ioc.OrderedConfiguration;
026import org.apache.tapestry5.ioc.ServiceBinder;
027import org.apache.tapestry5.ioc.annotations.Autobuild;
028import org.apache.tapestry5.ioc.annotations.Contribute;
029import org.apache.tapestry5.ioc.annotations.Marker;
030import org.apache.tapestry5.ioc.annotations.Symbol;
031import org.apache.tapestry5.services.*;
032import org.apache.tapestry5.services.transform.ControlledPackageType;
033
034import javax.servlet.http.Cookie;
035import java.util.Map;
036
037/**
038 * {@link org.apache.tapestry5.services.TapestryModule} has gotten too complicated and it is nice to demarkate public
039 * (and stable) from internal (and volatile).
040 */
041@Marker(Core.class)
042public class InternalModule
043{
044
045    private final RequestGlobals requestGlobals;
046
047    private final InvalidationEventHub classesInvalidationEventHub;
048
049    public InternalModule(RequestGlobals requestGlobals,
050
051                          @ComponentClasses
052                          InvalidationEventHub classesInvalidationEventHub)
053    {
054        this.requestGlobals = requestGlobals;
055        this.classesInvalidationEventHub = classesInvalidationEventHub;
056    }
057
058    /**
059     * Bind all the private/internal services of Tapestry.
060     */
061    public static void bind(ServiceBinder binder)
062    {
063        binder.bind(PersistentFieldManager.class, PersistentFieldManagerImpl.class);
064        binder.bind(TemplateParser.class, TemplateParserImpl.class);
065        binder.bind(PageResponseRenderer.class, PageResponseRendererImpl.class);
066        binder.bind(PageMarkupRenderer.class, PageMarkupRendererImpl.class);
067        binder.bind(LinkSource.class, LinkSourceImpl.class);
068        binder.bind(LocalizationSetter.class, LocalizationSetterImpl.class);
069        binder.bind(PageElementFactory.class, PageElementFactoryImpl.class);
070        binder.bind(ResourceStreamer.class, ResourceStreamerImpl.class);
071        binder.bind(ClientPersistentFieldStorage.class, ClientPersistentFieldStorageImpl.class);
072        binder.bind(PageRenderQueue.class, PageRenderQueueImpl.class);
073        binder.bind(AjaxPartialResponseRenderer.class, AjaxPartialResponseRendererImpl.class);
074        binder.bind(PageContentTypeAnalyzer.class, PageContentTypeAnalyzerImpl.class);
075        binder.bind(ComponentPageElementResourcesSource.class, ComponentPageElementResourcesSourceImpl.class);
076        binder.bind(RequestSecurityManager.class, RequestSecurityManagerImpl.class);
077        binder.bind(InternalRequestGlobals.class, InternalRequestGlobalsImpl.class);
078        binder.bind(EndOfRequestEventHub.class);
079        binder.bind(ResponseCompressionAnalyzer.class, ResponseCompressionAnalyzerImpl.class);
080        binder.bind(ComponentModelSource.class);
081        binder.bind(AssetResourceLocator.class);
082        binder.bind(JavaScriptStackPathConstructor.class);
083        binder.bind(AjaxFormUpdateController.class);
084        binder.bind(ResourceDigestManager.class, ResourceDigestManagerImpl.class);
085        binder.bind(RequestPageCache.class, NonPoolingRequestPageCacheImpl.class);
086        binder.bind(ComponentInstantiatorSource.class);
087        binder.bind(InternalComponentInvalidationEventHub.class);
088    }
089
090    /**
091     * Chooses one of two implementations, based on the configured mode.
092     */
093    public static ActionRenderResponseGenerator buildActionRenderResponseGenerator(
094
095            @Symbol(SymbolConstants.SUPPRESS_REDIRECT_FROM_ACTION_REQUESTS)
096            boolean immediateMode,
097
098            ObjectLocator locator)
099    {
100        if (immediateMode)
101            return locator.autobuild(ImmediateActionRenderResponseGenerator.class);
102
103        return locator.autobuild(ActionRenderResponseGeneratorImpl.class);
104    }
105
106    public PageLoader buildPageLoader(@Autobuild
107                                      PageLoaderImpl service,
108
109                                      @ComponentTemplates
110                                      InvalidationEventHub templatesHub,
111
112                                      @ComponentMessages
113                                      InvalidationEventHub messagesHub)
114    {
115        // TODO: We could combine these three using chain-of-command.
116
117        classesInvalidationEventHub.addInvalidationListener(service);
118        templatesHub.addInvalidationListener(service);
119        messagesHub.addInvalidationListener(service);
120
121        return service;
122    }
123
124    public PageSource buildPageSource(@Autobuild
125                                      PageSourceImpl service,
126
127                                      @ComponentTemplates
128                                      InvalidationEventHub templatesHub,
129
130                                      @ComponentMessages
131                                      InvalidationEventHub messagesHub)
132    {
133        // This covers invalidations due to changes to classes
134
135        classesInvalidationEventHub.addInvalidationListener(service);
136
137        // This covers invalidation due to changes to message catalogs (properties files)
138
139        messagesHub.addInvalidationListener(service);
140
141        // ... and this covers invalidations due to changes to templates
142
143        templatesHub.addInvalidationListener(service);
144
145        return service;
146    }
147
148    public ComponentClassCache buildComponentClassCache(@Autobuild
149                                                        ComponentClassCacheImpl service)
150    {
151        classesInvalidationEventHub.addInvalidationListener(service);
152
153        return service;
154    }
155
156    public CookieSource buildCookieSource()
157    {
158        return new CookieSource()
159        {
160
161            public Cookie[] getCookies()
162            {
163                return requestGlobals.getHTTPServletRequest().getCookies();
164            }
165        };
166    }
167
168    public CookieSink buildCookieSink()
169    {
170        return new CookieSink()
171        {
172
173            public void addCookie(Cookie cookie)
174            {
175                requestGlobals.getHTTPServletResponse().addCookie(cookie);
176            }
177        };
178    }
179
180    public PageActivationContextCollector buildPageActivationContextCollector(@Autobuild
181                                                                              PageActivationContextCollectorImpl service)
182    {
183        classesInvalidationEventHub.addInvalidationListener(service);
184
185        return service;
186    }
187
188    /**
189     * @since 5.1.0.0
190     */
191    public StringInterner buildStringInterner(@Autobuild
192                                              StringInternerImpl service)
193    {
194        classesInvalidationEventHub.addInvalidationListener(service);
195
196        return service;
197    }
198
199    /**
200     * Contributes:
201     * <dl>
202     * <dt>LinkDecoration (instance of {@link LinkDecorationListener})</dt>
203     * <dd>Triggers events for notifications about links</dd>
204     * <dl>
205     *
206     * @since 5.2.0
207     */
208    public static void contributeLinkSource(OrderedConfiguration<LinkCreationListener2> configuration)
209    {
210        configuration.addInstance("LinkDecoration", LinkDecorationListener.class);
211    }
212
213    /**
214     * Contributes packages identified by {@link ComponentClassResolver#getControlledPackageMapping()}.
215     *
216     * @since 5.3
217     */
218    @Contribute(ComponentInstantiatorSource.class)
219    public static void configureControlledPackagesFromComponentClassResolver(
220            MappedConfiguration<String, ControlledPackageType> configuration, ComponentClassResolver resolver)
221    {
222        for (Map.Entry<String, ControlledPackageType> entry : resolver.getControlledPackageMapping().entrySet())
223        {
224            configuration.add(entry.getKey(), entry.getValue());
225        }
226    }
227}