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