View Javadoc

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