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    
015    package org.apache.tapestry5.internal.services;
016    
017    import org.apache.tapestry5.SymbolConstants;
018    import org.apache.tapestry5.internal.pageload.PageLoaderImpl;
019    import org.apache.tapestry5.internal.services.ajax.AjaxFormUpdateController;
020    import org.apache.tapestry5.internal.services.javascript.JavaScriptStackPathConstructor;
021    import org.apache.tapestry5.internal.structure.ComponentPageElementResourcesSource;
022    import org.apache.tapestry5.internal.structure.ComponentPageElementResourcesSourceImpl;
023    import org.apache.tapestry5.ioc.MappedConfiguration;
024    import org.apache.tapestry5.ioc.ObjectLocator;
025    import org.apache.tapestry5.ioc.OrderedConfiguration;
026    import org.apache.tapestry5.ioc.ServiceBinder;
027    import org.apache.tapestry5.ioc.annotations.Autobuild;
028    import org.apache.tapestry5.ioc.annotations.Contribute;
029    import org.apache.tapestry5.ioc.annotations.Marker;
030    import org.apache.tapestry5.ioc.annotations.Symbol;
031    import org.apache.tapestry5.services.*;
032    import org.apache.tapestry5.services.transform.ControlledPackageType;
033    
034    import javax.servlet.http.Cookie;
035    import 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)
042    public 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    }