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