001    package org.apache.turbine.services.template;
002    
003    
004    /*
005     * Licensed to the Apache Software Foundation (ASF) under one
006     * or more contributor license agreements.  See the NOTICE file
007     * distributed with this work for additional information
008     * regarding copyright ownership.  The ASF licenses this file
009     * to you under the Apache License, Version 2.0 (the
010     * "License"); you may not use this file except in compliance
011     * with the License.  You may obtain a copy of the License at
012     *
013     *   http://www.apache.org/licenses/LICENSE-2.0
014     *
015     * Unless required by applicable law or agreed to in writing,
016     * software distributed under the License is distributed on an
017     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
018     * KIND, either express or implied.  See the License for the
019     * specific language governing permissions and limitations
020     * under the License.
021     */
022    
023    
024    import java.io.File;
025    import java.util.Collections;
026    import java.util.HashMap;
027    import java.util.Map;
028    
029    import org.apache.commons.configuration.Configuration;
030    import org.apache.commons.lang.StringUtils;
031    import org.apache.commons.logging.Log;
032    import org.apache.commons.logging.LogFactory;
033    import org.apache.fulcrum.factory.FactoryException;
034    import org.apache.fulcrum.factory.FactoryService;
035    import org.apache.turbine.Turbine;
036    import org.apache.turbine.TurbineConstants;
037    import org.apache.turbine.modules.Assembler;
038    import org.apache.turbine.modules.Layout;
039    import org.apache.turbine.modules.Loader;
040    import org.apache.turbine.modules.Navigation;
041    import org.apache.turbine.modules.Page;
042    import org.apache.turbine.modules.Screen;
043    import org.apache.turbine.services.InitializationException;
044    import org.apache.turbine.services.TurbineBaseService;
045    import org.apache.turbine.services.TurbineServices;
046    import org.apache.turbine.services.assemblerbroker.AssemblerBrokerService;
047    import org.apache.turbine.services.servlet.TurbineServlet;
048    import org.apache.turbine.services.template.mapper.BaseTemplateMapper;
049    import org.apache.turbine.services.template.mapper.ClassMapper;
050    import org.apache.turbine.services.template.mapper.DirectMapper;
051    import org.apache.turbine.services.template.mapper.DirectTemplateMapper;
052    import org.apache.turbine.services.template.mapper.LayoutTemplateMapper;
053    import org.apache.turbine.services.template.mapper.Mapper;
054    import org.apache.turbine.services.template.mapper.ScreenTemplateMapper;
055    import org.apache.turbine.util.RunData;
056    import org.apache.turbine.util.uri.URIConstants;
057    
058    /**
059     * This service provides a method for mapping templates to their
060     * appropriate Screens or Navigations.  It also allows templates to
061     * define a layout/navigations/screen modularization within the
062     * template structure.  It also performs caching if turned on in the
063     * properties file.
064     *
065     * This service is not bound to a specific templating engine but we
066     * will use the Velocity templating engine for the examples. It is
067     * available by using the VelocityService.
068     *
069     * This assumes the following properties in the Turbine configuration:
070     *
071     * <pre>
072     * # Register the VelocityService for the "vm" extension.
073     * services.VelocityService.template.extension=vm
074     *
075     * # Default Java class for rendering a Page in this service
076     * # (must be found on the class path (org.apache.turbine.modules.page.VelocityPage))
077     * services.VelocityService.default.page = VelocityPage
078     *
079     * # Default Java class for rendering a Screen in this service
080     * # (must be found on the class path (org.apache.turbine.modules.screen.VelocityScreen))
081     * services.VelocityService.default.screen=VelocityScreen
082     *
083     * # Default Java class for rendering a Layout in this service
084     * # (must be found on the class path (org.apache.turbine.modules.layout.VelocityOnlyLayout))
085     * services.VelocityService.default.layout = VelocityOnlyLayout
086     *
087     * # Default Java class for rendering a Navigation in this service
088     * # (must be found on the class path (org.apache.turbine.modules.navigation.VelocityNavigation))
089     * services.VelocityService.default.navigation=VelocityNavigation
090     *
091     * # Default Template Name to be used as Layout. If nothing else is
092     * # found, return this as the default name for a layout
093     * services.VelocityService.default.layout.template = Default.vm
094     * </pre>
095     * If you want to render a template, a search path is used to find
096     * a Java class which might provide information for the context of
097     * this template.
098     *
099     * If you request e.g. the template screen
100     *
101     * about,directions,Driving.vm
102     *
103     * then the following class names are searched (on the module search
104     * path):
105     *
106     * 1. about.directions.Driving     &lt;- direct matching the template to the class name
107     * 2. about.directions.Default     &lt;- matching the package, class name is Default
108     * 3. about.Default                &lt;- stepping up in the package hierarchy, looking for Default
109     * 4. Default                      &lt;- Class called "Default" without package
110     * 5. VelocityScreen               &lt;- The class configured by the Service (VelocityService) to
111     *
112     * And if you have the following module packages configured:
113     *
114     * module.packages = org.apache.turbine.modules, com.mycorp.modules
115     *
116     * then the class loader will look for
117     *
118     * org.apache.turbine.modules.screens.about.directions.Driving
119     * com.mycorp.modules.screens.about.directions.Driving
120     * org.apache.turbine.modules.screens.about.directions.Default
121     * com.mycorp.modules.screens.about.directions.Default
122     * org.apache.turbine.modules.screens.about.Default
123     * com.mycorp.modules.screens.about.Default
124     * org.apache.turbine.modules.screens.Default
125     * com.mycorp.modules.screens.Default
126     * org.apache.turbine.modules.screens.VelocityScreen
127     * com.mycorp.modules.screens.VelocityScreen
128     *
129     * Most of the times, you don't have any backing Java class for a
130     * template screen, so the first match will be
131     * org.apache.turbine.modules.screens.VelocityScreen
132     * which then renders your screen.
133     *
134     * Please note, that your Screen Template (Driving.vm) must exist!
135     * If it does not exist, the Template Service will report an error.
136     *
137     * Once the screen is found, the template service will look for
138     * the Layout and Navigation templates of your Screen. Here, the
139     * template service looks for matching template names!
140     *
141     * Consider our example:  about,directions,Driving.vm (Screen Name)
142     *
143     * Now the template service will look for the following Navigation
144     * and Layout templates:
145     *
146     * 1. about,directions,Driving.vm      &lt;- exact match
147     * 2. about,directions,Default.vm      &lt;- package match, Default name
148     * 3. about,Default.vm                 &lt;- stepping up in the hierarchy
149     * 4. Default.vm                       &lt;- The name configured as default.layout.template
150     *                                        in the Velocity service.
151     *
152     * And now Hennings' two golden rules for using templates:
153     *
154     * Many examples and docs from older Turbine code show template pathes
155     * with a slashes. Repeat after me: "TEMPLATE NAMES NEVER CONTAIN SLASHES!"
156     *
157     * Many examples and docs from older Turbine code show templates that start
158     * with "/". This is not only a violation of the rule above but actively breaks
159     * things like loading templates from a jar with the velocity jar loader. Repeat
160     * after me: "TEMPLATE NAMES ARE NOT PATHES. THEY'RE NOT ABSOLUTE AND HAVE NO
161     * LEADING /".
162     *
163     * If you now wonder how a template name is mapped to a file name: This is
164     * scope of the templating engine. Velocity e.g. has this wonderful option to
165     * load templates from jar archives. There is no single file but you tell
166     * velocity "get about,directions,Driving.vm" and it returns the rendered
167     * template. This is not the job of the Templating Service but of the Template
168     * rendering services like VelocityService.
169     *
170     * @author <a href="mailto:john.mcnally@clearink.com">John D. McNally</a>
171     * @author <a href="mailto:mbryson@mont.mindspring.com">Dave Bryson</a>
172     * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
173     * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
174     * @author <a href="mailto:ilkka.priha@simsoft.fi">Ilkka Priha</a>
175     * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
176     * @version $Id: TurbineTemplateService.java 1199089 2011-11-08 03:14:28Z tv $
177     */
178    public class TurbineTemplateService
179        extends TurbineBaseService
180        implements TemplateService
181    {
182        /** Logging */
183        private static Log log = LogFactory.getLog(TurbineTemplateService.class);
184    
185        /** Represents Page Objects */
186        public static final int PAGE_KEY = 0;
187    
188        /** Represents Screen Objects */
189        public static final int SCREEN_KEY = 1;
190    
191        /** Represents Layout Objects */
192        public static final int LAYOUT_KEY = 2;
193    
194        /** Represents Navigation Objects */
195        public static final int NAVIGATION_KEY = 3;
196    
197        /** Represents Layout Template Objects */
198        public static final int LAYOUT_TEMPLATE_KEY = 4;
199    
200        /** Represents Layout Template Objects */
201        public static final String LAYOUT_TEMPLATE_NAME = "layout.template";
202    
203        /** Represents Screen Template Objects */
204        public static final int SCREEN_TEMPLATE_KEY = 5;
205    
206        /** Represents Screen Template Objects */
207        public static final String SCREEN_TEMPLATE_NAME = "screen.template";
208    
209        /** Represents Navigation Template Objects */
210        public static final int NAVIGATION_TEMPLATE_KEY = 6;
211    
212        /** Represents Navigation Template Objects */
213        public static final String NAVIGATION_TEMPLATE_NAME = "navigation.template";
214    
215        /** Number of different Template Types that we know of */
216        public static final int TEMPLATE_TYPES = 7;
217    
218        /** Here we register the mapper objects for our various object types */
219        private Mapper [] mapperRegistry = null;
220    
221        /**
222         * The default file extension used as a registry key when a
223         * template's file extension cannot be determined.
224         *
225         * @deprecated. Use TemplateService.DEFAULT_EXTENSION_VALUE.
226         */
227        protected static final String NO_FILE_EXT = TemplateService.DEFAULT_EXTENSION_VALUE;
228    
229    
230        /** Flag set if cache is to be used. */
231        private boolean useCache = false;
232    
233        /** Default extension for templates. */
234        private String defaultExtension;
235    
236        /** Default template without the default extension. */
237        private String defaultTemplate;
238    
239        /**
240         * The mappings of template file extensions to {@link
241         * org.apache.turbine.services.template.TemplateEngineService}
242         * implementations. Implementing template engines can locate
243         * templates within the capability of any resource loaders they
244         * may possess, and other template engines are stuck with file
245         * based template hierarchy only.
246         */
247        private Map<String, TemplateEngineService> templateEngineRegistry = null;
248    
249        /**
250         * C'tor
251         */
252        public TurbineTemplateService()
253        {
254            // empty
255        }
256    
257        /**
258         * Called the first time the Service is used.
259         *
260         * @exception InitializationException Something went wrong when
261         *                                     setting up the Template Service.
262         */
263        @Override
264        public void init()
265            throws InitializationException
266        {
267            // Get the configuration for the template service.
268            Configuration config = getConfiguration();
269    
270            // Get the default extension to use if nothing else is applicable.
271            defaultExtension = config.getString(TemplateService.DEFAULT_EXTENSION_KEY,
272                TemplateService.DEFAULT_EXTENSION_VALUE);
273    
274            defaultTemplate =  config.getString(TemplateService.DEFAULT_TEMPLATE_KEY,
275                TemplateService.DEFAULT_TEMPLATE_VALUE);
276    
277            // Check to see if we are going to be caching modules.
278            // Aaargh, who moved this _out_ of the TemplateService package?
279            useCache = Turbine.getConfiguration().getBoolean(TurbineConstants.MODULE_CACHE_KEY,
280                TurbineConstants.MODULE_CACHE_DEFAULT);
281    
282            log.debug("Default Extension: " + defaultExtension);
283            log.debug("Default Template:  " + defaultTemplate);
284            log.debug("Use Caching:       " + useCache);
285    
286            templateEngineRegistry = Collections.synchronizedMap(new HashMap<String, TemplateEngineService>());
287    
288            initMapper(config);
289            setInit(true);
290        }
291    
292        /**
293         * Returns true if the Template Service has caching activated
294         *
295         * @return true if Caching is active.
296         */
297        public boolean isCaching()
298        {
299            return useCache;
300        }
301    
302        /**
303         * Get the default template name extension specified
304         * in the template service properties. If no extension
305         * is defined, return the empty string.
306         *
307         * @return The default extension.
308         */
309        public String getDefaultExtension()
310        {
311            return StringUtils.isNotEmpty(defaultExtension) ? defaultExtension : "";
312        }
313    
314        /**
315         * Return Extension for a supplied template
316         *
317         * @param template The template name
318         *
319         * @return extension The extension for the supplied template
320         */
321        public String getExtension(String template)
322        {
323            if (StringUtils.isEmpty(template))
324            {
325                return getDefaultExtension();
326            }
327    
328            int dotIndex = template.lastIndexOf(EXTENSION_SEPARATOR);
329    
330            return (dotIndex < 0) ? getDefaultExtension() : template.substring(dotIndex + 1);
331        }
332    
333    
334        /**
335         * Returns the Default Template Name with the Default Extension.
336         * If the extension is unset, return only the template name
337         *
338         * @return The default template Name
339         */
340        public String getDefaultTemplate()
341        {
342            StringBuffer sb = new StringBuffer();
343            sb.append(defaultTemplate);
344            if (StringUtils.isNotEmpty(defaultExtension))
345            {
346                sb.append(EXTENSION_SEPARATOR);
347                sb.append(getDefaultExtension());
348            }
349            return sb.toString();
350        }
351    
352        /**
353         * Get the default page module name of the template engine
354         * service corresponding to the default template name extension.
355         *
356         * @return The default page module name.
357         */
358        public String getDefaultPage()
359        {
360            return getDefaultPageName(getDefaultTemplate());
361        }
362    
363        /**
364         * Get the default screen module name of the template engine
365         * service corresponding to the default template name extension.
366         *
367         * @return The default screen module name.
368         */
369        public String getDefaultScreen()
370        {
371            return getDefaultScreenName(getDefaultTemplate());
372        }
373    
374        /**
375         * Get the default layout module name of the template engine
376         * service corresponding to the default template name extension.
377         *
378         * @return The default layout module name.
379         */
380        public String getDefaultLayout()
381        {
382            return getDefaultLayoutName(getDefaultTemplate());
383        }
384    
385        /**
386         * Get the default navigation module name of the template engine
387         * service corresponding to the default template name extension.
388         *
389         * @return The default navigation module name.
390         */
391        public String getDefaultNavigation()
392        {
393            return getDefaultNavigationName(getDefaultTemplate());
394        }
395    
396        /**
397         * Get the default layout template name of the template engine
398         * service corresponding to the default template name extension.
399         *
400         * @return The default layout template name.
401         */
402        public String getDefaultLayoutTemplate()
403        {
404            return getDefaultLayoutTemplateName(getDefaultTemplate());
405        }
406    
407        /**
408         * Get the default page module name of the template engine
409         * service corresponding to the template name extension of
410         * the named template.
411         *
412         * @param template The template name.
413         * @return The default page module name.
414         */
415        public String getDefaultPageName(String template)
416        {
417            return (mapperRegistry[PAGE_KEY]).getDefaultName(template);
418        }
419    
420        /**
421         * Get the default screen module name of the template engine
422         * service corresponding to the template name extension of
423         * the named template.
424         *
425         * @param template The template name.
426         * @return The default screen module name.
427         */
428        public String getDefaultScreenName(String template)
429        {
430            return (mapperRegistry[SCREEN_KEY]).getDefaultName(template);
431        }
432    
433        /**
434         * Get the default layout module name of the template engine
435         * service corresponding to the template name extension of
436         * the named template.
437         *
438         * @param template The template name.
439         * @return The default layout module name.
440         */
441        public String getDefaultLayoutName(String template)
442        {
443            return (mapperRegistry[LAYOUT_KEY]).getDefaultName(template);
444        }
445    
446        /**
447         * Get the default navigation module name of the template engine
448         * service corresponding to the template name extension of
449         * the named template.
450         *
451         * @param template The template name.
452         * @return The default navigation module name.
453         */
454        public String getDefaultNavigationName(String template)
455        {
456            return (mapperRegistry[NAVIGATION_KEY]).getDefaultName(template);
457        }
458    
459        /**
460         * Get the default layout template name of the template engine
461         * service corresponding to the template name extension of
462         * the named template.
463         *
464         * @param template The template name.
465         * @return The default layout template name.
466         */
467        public String getDefaultLayoutTemplateName(String template)
468        {
469            return (mapperRegistry[LAYOUT_TEMPLATE_KEY]).getDefaultName(template);
470        }
471    
472        /**
473         * Find the default page module name for the given request.
474         *
475         * @param data The encapsulation of the request to retrieve the
476         *             default page for.
477         * @return The default page module name.
478         */
479        public String getDefaultPageName(RunData data)
480        {
481            String template = data.getParameters().get(URIConstants.CGI_TEMPLATE_PARAM);
482            return (template != null) ?
483                getDefaultPageName(template) : getDefaultPage();
484        }
485    
486        /**
487         * Find the default layout module name for the given request.
488         *
489         * @param data The encapsulation of the request to retrieve the
490         *             default layout for.
491         * @return The default layout module name.
492         */
493        public String getDefaultLayoutName(RunData data)
494        {
495            String template = data.getParameters().get(URIConstants.CGI_TEMPLATE_PARAM);
496            return (template != null) ?
497                getDefaultLayoutName(template) : getDefaultLayout();
498        }
499    
500        /**
501         * Locate and return the name of the screen module to be used
502         * with the named screen template.
503         *
504         * @param template The screen template name.
505         * @return The found screen module name.
506         * @exception Exception, a generic exception.
507         */
508        public String getScreenName(String template)
509            throws Exception
510        {
511            return (mapperRegistry[SCREEN_KEY]).getMappedName(template);
512        }
513    
514        /**
515         * Locate and return the name of the layout module to be used
516         * with the named layout template.
517         *
518         * @param template The layout template name.
519         * @return The found layout module name.
520         * @exception Exception, a generic exception.
521         */
522        public String getLayoutName(String template)
523            throws Exception
524        {
525            return (mapperRegistry[LAYOUT_KEY]).getMappedName(template);
526        }
527    
528        /**
529         * Locate and return the name of the navigation module to be used
530         * with the named navigation template.
531         *
532         * @param template The navigation template name.
533         * @return The found navigation module name.
534         * @exception Exception, a generic exception.
535         */
536        public String getNavigationName(String template)
537            throws Exception
538        {
539            return (mapperRegistry[NAVIGATION_KEY]).getMappedName(template);
540        }
541    
542        /**
543         * Locate and return the name of the screen template corresponding
544         * to the given template name parameter. This might return null if
545         * the screen is not found!
546         *
547         * @param template The template name parameter.
548         * @return The found screen template name.
549         * @exception Exception, a generic exception.
550         */
551        public String getScreenTemplateName(String template)
552            throws Exception
553        {
554            return (mapperRegistry[SCREEN_TEMPLATE_KEY]).getMappedName(template);
555        }
556    
557        /**
558         * Locate and return the name of the layout template corresponding
559         * to the given screen template name parameter.
560         *
561         * @param template The template name parameter.
562         * @return The found screen template name.
563         * @exception Exception, a generic exception.
564         */
565        public String getLayoutTemplateName(String template)
566            throws Exception
567        {
568            return (mapperRegistry[LAYOUT_TEMPLATE_KEY]).getMappedName(template);
569        }
570    
571        /**
572         * Locate and return the name of the navigation template corresponding
573         * to the given template name parameter. This might return null if
574         * the navigation is not found!
575         *
576         * @param template The template name parameter.
577         * @return The found navigation template name.
578         * @exception Exception, a generic exception.
579         */
580        public String getNavigationTemplateName(String template)
581            throws Exception
582        {
583            return (mapperRegistry[NAVIGATION_TEMPLATE_KEY]).getMappedName(template);
584        }
585    
586        /**
587         * Translates the supplied template paths into their Turbine-canonical
588         * equivalent (probably absolute paths). This is used if the templating
589         * engine (e.g. JSP) does not provide any means to load a page but
590         * the page path is passed to the servlet container.
591         *
592         * @param templatePaths An array of template paths.
593         * @return An array of translated template paths.
594         * @deprecated Each template engine service should know how to translate
595         *             a request onto a file.
596         */
597        @Deprecated
598        public String[] translateTemplatePaths(String[] templatePaths)
599        {
600            for (int i = 0; i < templatePaths.length; i++)
601            {
602                templatePaths[i] = TurbineServlet.getRealPath(templatePaths[i]);
603            }
604            return templatePaths;
605        }
606    
607        /**
608         * Delegates to the appropriate {@link
609         * org.apache.turbine.services.template.TemplateEngineService} to
610         * check the existance of the specified template.
611         *
612         * @param template The template to check for the existance of.
613         * @param templatePaths The paths to check for the template.
614         * @deprecated Use templateExists from the various Templating Engines
615         */
616        @Deprecated
617        public boolean templateExists(String template,
618            String[] templatePaths)
619        {
620            for (int i = 0; i < templatePaths.length; i++)
621            {
622                if (new File(templatePaths[i], template).exists())
623                {
624                    return true;
625                }
626            }
627            return false;
628        }
629    
630        /**
631         * Registers the provided template engine for use by the
632         * <code>TemplateService</code>.
633         *
634         * @param service The <code>TemplateEngineService</code> to register.
635         */
636        public synchronized void registerTemplateEngineService(TemplateEngineService service)
637        {
638            String[] exts = service.getAssociatedFileExtensions();
639    
640            for (int i = 0; i < exts.length; i++)
641            {
642                templateEngineRegistry.put(exts[i], service);
643            }
644        }
645    
646        /**
647         * The {@link org.apache.turbine.services.template.TemplateEngineService}
648         * associated with the specified template's file extension.
649         *
650         * @param template The template name.
651         * @return The template engine service.
652         */
653        public TemplateEngineService getTemplateEngineService(String template)
654        {
655            return templateEngineRegistry.get(getExtension(template));
656        }
657    
658        /**
659         * Register a template Mapper to the service. This Mapper
660         * performs the template mapping and searching for a specific
661         * object type which is managed by the TemplateService.
662         *
663         * @param templateKey  One of the _KEY constants for the Template object types.
664         * @param mapper  An object which implements the Mapper interface.
665         */
666        private void registerMapper(int templateKey, Mapper mapper)
667        {
668            mapper.init();
669            mapperRegistry[templateKey] = mapper;
670        }
671    
672        /**
673         * Load and configure the Template mappers for
674         * the Template Service.
675         *
676         * @param conf The current configuration object.
677         * @throws InitializationException A problem occurred trying to set up the mappers.
678         */
679        @SuppressWarnings("unchecked")
680        private void initMapper(Configuration conf)
681                throws InitializationException
682        {
683            // Create a registry with the number of Template Types managed by this service.
684            // We could use a List object here and extend the number of managed objects
685            // dynamically. However, by using an Object Array, we get much more performance
686            // out of the Template Service.
687            mapperRegistry = new Mapper[TEMPLATE_TYPES];
688    
689            String [] mapperNames = new String [] {
690                Page.NAME, Screen.NAME, Layout.NAME, Navigation.NAME,
691                LAYOUT_TEMPLATE_NAME, SCREEN_TEMPLATE_NAME, NAVIGATION_TEMPLATE_NAME
692            };
693    
694            Class<?> [] mapperKeys = new Class<?> [] {
695                Page.class, Screen.class, Layout.class, Navigation.class,
696                Layout.class, Screen.class, Navigation.class
697            };
698    
699            String [] mapperClasses = new String [] {
700                DirectMapper.class.getName(),
701                ClassMapper.class.getName(),
702                ClassMapper.class.getName(),
703                ClassMapper.class.getName(),
704                LayoutTemplateMapper.class.getName(),
705                ScreenTemplateMapper.class.getName(),
706                DirectTemplateMapper.class.getName()
707            };
708    
709            AssemblerBrokerService ab = (AssemblerBrokerService)TurbineServices.getInstance()
710                                            .getService(AssemblerBrokerService.SERVICE_NAME);
711    
712            int [] mapperCacheSize = new int [mapperKeys.length];
713            Loader<? extends Assembler> [] mapperLoader = new Loader<?>[mapperKeys.length];
714    
715            for (int i = 0; i < mapperKeys.length; i++)
716            {
717                mapperLoader[i] = ab.getLoader((Class<? extends Assembler>)mapperKeys[i]);
718                mapperCacheSize[i] = (mapperLoader[i] != null) ? mapperLoader[i].getCacheSize() : 0;
719            }
720    
721            // HACK: to achieve the same behavior as before
722            mapperLoader[LAYOUT_TEMPLATE_KEY] = null;
723            mapperLoader[SCREEN_TEMPLATE_KEY] = null;
724            mapperLoader[NAVIGATION_TEMPLATE_KEY] = null;
725    
726            String [] mapperDefaultProperty = new String [] {
727                TemplateEngineService.DEFAULT_PAGE,
728                TemplateEngineService.DEFAULT_SCREEN,
729                TemplateEngineService.DEFAULT_LAYOUT,
730                TemplateEngineService.DEFAULT_NAVIGATION,
731                TemplateEngineService.DEFAULT_LAYOUT_TEMPLATE,
732                TemplateEngineService.DEFAULT_SCREEN_TEMPLATE,
733                TemplateEngineService.DEFAULT_NAVIGATION_TEMPLATE
734            };
735    
736            char [] mapperSeparator = new char [] { '.', '.', '.', '.', '/', '/', '/' };
737    
738            String [] mapperPrefix = new String [] {
739                null, null, null, null,
740                Layout.PREFIX,
741                Screen.PREFIX,
742                Navigation.PREFIX  };
743    
744            for (int i = 0; i < TEMPLATE_TYPES; i++)
745            {
746                StringBuffer mapperProperty = new StringBuffer();
747                mapperProperty.append("mapper.");
748                mapperProperty.append(mapperNames[i]);
749                mapperProperty.append(".class");
750    
751                String mapperClass =
752                        conf.getString(mapperProperty.toString(), mapperClasses[i]);
753    
754                log.info("Using " + mapperClass + " to map " + mapperNames[i] + " elements");
755    
756                Mapper tm = null;
757    
758                try
759                {
760                        FactoryService factory = (FactoryService)TurbineServices.getInstance().getService(FactoryService.ROLE);
761                        tm = (Mapper) factory.getInstance(mapperClass);
762                }
763                catch (FactoryException e)
764                {
765                            throw new InitializationException("", e);
766                        }
767    
768                tm.setUseCache(useCache);
769                tm.setCacheSize(mapperCacheSize[i]);
770                tm.setDefaultProperty(mapperDefaultProperty[i]);
771                tm.setSeparator(mapperSeparator[i]);
772    
773                if ((mapperLoader[i] != null) && (tm instanceof ClassMapper))
774                {
775                    ((ClassMapper) tm).setLoader(mapperLoader[i]);
776                }
777    
778                if ((mapperPrefix[i] != null) && (tm instanceof BaseTemplateMapper))
779                {
780                    ((BaseTemplateMapper) tm).setPrefix(mapperPrefix[i]);
781                }
782    
783                registerMapper(i, tm);
784            }
785        }
786    }