001    // Copyright 2007, 2008 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.tutorial.services;
016    
017    import org.apache.tapestry5.SymbolConstants;
018    import org.apache.tapestry5.ioc.MappedConfiguration;
019    import org.apache.tapestry5.ioc.OrderedConfiguration;
020    import org.apache.tapestry5.ioc.annotations.Local;
021    import org.apache.tapestry5.services.Request;
022    import org.apache.tapestry5.services.RequestFilter;
023    import org.apache.tapestry5.services.RequestHandler;
024    import org.apache.tapestry5.services.Response;
025    import org.slf4j.Logger;
026    
027    import java.io.IOException;
028    
029    /**
030     * This module is automatically included as part of the Tapestry IoC Registry, it's a good place to configure and extend
031     * Tapestry, or to place your own services.
032     */
033    public class AppModule
034    {
035        public static void contributeApplicationDefaults(
036                MappedConfiguration<String, String> configuration)
037        {
038            // Contributions to ApplicationDefaults will override any contributions to
039            // FactoryDefaults (with the same key). Here we're restricting the supported
040            // locales to just "en" (English). As you add localised message catalogs and other assets,
041            // you can extend this list of locales (it's a comma seperated series of locale names;
042            // the first locale name is the default when there's no reasonable match).
043    
044            configuration.add(SymbolConstants.SUPPORTED_LOCALES, "en");
045            configuration.add(SymbolConstants.PRODUCTION_MODE, "false");
046        }
047    
048        /**
049         * This is a service definition, the service will be named TimingFilter. The interface, RequestFilter, is used
050         * within the RequestHandler service pipeline, which is built from the RequestHandler service configuration.
051         * Tapestry IoC is responsible for passing in an appropriate Log instance. Requests for static resources are handled
052         * at a higher level, so this filter will only be invoked for Tapestry related requests.
053         */
054        public RequestFilter buildTimingFilter(final Logger logger)
055        {
056            return new RequestFilter()
057            {
058                public boolean service(Request request, Response response, RequestHandler handler)
059                        throws IOException
060                {
061                    long startTime = System.currentTimeMillis();
062    
063                    try
064                    {
065                        // The reponsibility of a filter is to invoke the corresponding method
066                        // in the handler. When you chain multiple filters together, each filter
067                        // received a handler that is a bridge to the next filter.
068    
069                        return handler.service(request, response);
070                    }
071                    finally
072                    {
073                        long elapsed = System.currentTimeMillis() - startTime;
074    
075                        logger.info(String.format("Request time: %d ms", elapsed));
076                    }
077                }
078            };
079        }
080    
081        /**
082         * This is a contribution to the RequestHandler service configuration. This is how we extend Tapestry using the
083         * timing filter. A common use for this kind of filter is transaction management or security.
084         */
085        public void contributeRequestHandler(OrderedConfiguration<RequestFilter> configuration,
086    
087                                             @Local
088                                             RequestFilter filter)
089        {
090            // Each contribution to an ordered configuration has a name, When necessary, you may
091            // set constraints to precisely control the invocation order of the contributed filter
092            // within the pipeline.
093    
094            configuration.add("Timing", filter);
095        }
096    }