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.concurrent.ConcurrentHashMap;
26  import java.util.concurrent.ConcurrentMap;
27  
28  import org.apache.commons.configuration2.Configuration;
29  import org.apache.commons.lang3.StringUtils;
30  import org.apache.fulcrum.factory.FactoryException;
31  import org.apache.fulcrum.factory.FactoryService;
32  import org.apache.fulcrum.parser.ParameterParser;
33  import org.apache.logging.log4j.LogManager;
34  import org.apache.logging.log4j.Logger;
35  import org.apache.turbine.Turbine;
36  import org.apache.turbine.TurbineConstants;
37  import org.apache.turbine.modules.Assembler;
38  import org.apache.turbine.modules.Layout;
39  import org.apache.turbine.modules.Loader;
40  import org.apache.turbine.modules.Navigation;
41  import org.apache.turbine.modules.Page;
42  import org.apache.turbine.modules.Screen;
43  import org.apache.turbine.pipeline.PipelineData;
44  import org.apache.turbine.services.InitializationException;
45  import org.apache.turbine.services.TurbineBaseService;
46  import org.apache.turbine.services.TurbineServices;
47  import org.apache.turbine.services.assemblerbroker.AssemblerBrokerService;
48  import org.apache.turbine.services.servlet.ServletService;
49  import org.apache.turbine.services.template.mapper.BaseTemplateMapper;
50  import org.apache.turbine.services.template.mapper.ClassMapper;
51  import org.apache.turbine.services.template.mapper.DirectMapper;
52  import org.apache.turbine.services.template.mapper.DirectTemplateMapper;
53  import org.apache.turbine.services.template.mapper.LayoutTemplateMapper;
54  import org.apache.turbine.services.template.mapper.Mapper;
55  import org.apache.turbine.services.template.mapper.ScreenTemplateMapper;
56  import org.apache.turbine.util.uri.URIConstants;
57  
58  /**
59   * This service provides a method for mapping templates to their
60   * appropriate Screens or Navigations.  It also allows templates to
61   * define a layout/navigations/screen modularization within the
62   * template structure.  It also performs caching if turned on in the
63   * properties file.
64   *
65   * This service is not bound to a specific templating engine but we
66   * will use the Velocity templating engine for the examples. It is
67   * available by using the VelocityService.
68   *
69   * This assumes the following properties in the Turbine configuration:
70   *
71   * <pre>
72   * # Register the VelocityService for the "vm" extension.
73   * services.VelocityService.template.extension=vm
74   *
75   * # Default Java class for rendering a Page in this service
76   * # (must be found on the class path (org.apache.turbine.modules.page.VelocityPage))
77   * services.VelocityService.default.page = VelocityPage
78   *
79   * # Default Java class for rendering a Screen in this service
80   * # (must be found on the class path (org.apache.turbine.modules.screen.VelocityScreen))
81   * services.VelocityService.default.screen=VelocityScreen
82   *
83   * # Default Java class for rendering a Layout in this service
84   * # (must be found on the class path (org.apache.turbine.modules.layout.VelocityOnlyLayout))
85   * services.VelocityService.default.layout = VelocityOnlyLayout
86   *
87   * # Default Java class for rendering a Navigation in this service
88   * # (must be found on the class path (org.apache.turbine.modules.navigation.VelocityNavigation))
89   * services.VelocityService.default.navigation=VelocityNavigation
90   *
91   * # Default Template Name to be used as Layout. If nothing else is
92   * # found, return this as the default name for a layout
93   * services.VelocityService.default.layout.template = Default.vm
94   * </pre>
95   * If you want to render a template, a search path is used to find
96   * a Java class which might provide information for the context of
97   * this template.
98   *
99   * 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$
179  */
180 public class TurbineTemplateService
181     extends TurbineBaseService
182     implements TemplateService
183 {
184     /** Logging */
185     private static final Logger log = LogManager.getLogger(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:       {}", Boolean.valueOf(useCache));
295 
296         templateEngineRegistry = new ConcurrentHashMap<>();
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 ? getDefaultPageName(template) : getDefaultPage();
509     }
510 
511     /**
512      * Find the default layout module name for the given request.
513      *
514      * @param pipelineData The encapsulation of the request to retrieve the
515      *             default layout for.
516      * @return The default layout module name.
517      */
518     @Override
519     public String getDefaultLayoutName(PipelineData pipelineData)
520     {
521         ParameterParser pp = pipelineData.get(Turbine.class, ParameterParser.class);
522         String template = pp.get(URIConstants.CGI_TEMPLATE_PARAM);
523         return template != null ? getDefaultLayoutName(template) : getDefaultLayout();
524     }
525 
526     /**
527      * Locate and return the name of the screen module to be used
528      * with the named screen template.
529      *
530      * @param template The screen template name.
531      * @return The found screen module name.
532      * @throws Exception a generic exception.
533      */
534     @Override
535     public String getScreenName(String template)
536         throws Exception
537     {
538         return mapperRegistry[SCREEN_KEY].getMappedName(template);
539     }
540 
541     /**
542      * Locate and return the name of the layout module to be used
543      * with the named layout template.
544      *
545      * @param template The layout template name.
546      * @return The found layout module name.
547      * @throws Exception a generic exception.
548      */
549     @Override
550     public String getLayoutName(String template)
551         throws Exception
552     {
553         return mapperRegistry[LAYOUT_KEY].getMappedName(template);
554     }
555 
556     /**
557      * Locate and return the name of the navigation module to be used
558      * with the named navigation template.
559      *
560      * @param template The navigation template name.
561      * @return The found navigation module name.
562      * @throws Exception a generic exception.
563      */
564     @Override
565     public String getNavigationName(String template)
566         throws Exception
567     {
568         return mapperRegistry[NAVIGATION_KEY].getMappedName(template);
569     }
570 
571     /**
572      * Locate and return the name of the screen template corresponding
573      * to the given template name parameter. This might return null if
574      * the screen is not found!
575      *
576      * @param template The template name parameter.
577      * @return The found screen template name.
578      * @throws Exception a generic exception.
579      */
580     @Override
581     public String getScreenTemplateName(String template)
582         throws Exception
583     {
584         return mapperRegistry[SCREEN_TEMPLATE_KEY].getMappedName(template);
585     }
586 
587     /**
588      * Locate and return the name of the layout template corresponding
589      * to the given screen template name parameter.
590      *
591      * @param template The template name parameter.
592      * @return The found screen template name.
593      * @throws Exception a generic exception.
594      */
595     @Override
596     public String getLayoutTemplateName(String template)
597         throws Exception
598     {
599         return mapperRegistry[LAYOUT_TEMPLATE_KEY].getMappedName(template);
600     }
601 
602     /**
603      * Locate and return the name of the navigation template corresponding
604      * to the given template name parameter. This might return null if
605      * the navigation is not found!
606      *
607      * @param template The template name parameter.
608      * @return The found navigation template name.
609      * @throws Exception a generic exception.
610      */
611     @Override
612     public String getNavigationTemplateName(String template)
613         throws Exception
614     {
615         return mapperRegistry[NAVIGATION_TEMPLATE_KEY].getMappedName(template);
616     }
617 
618     /**
619      * Translates the supplied template paths into their Turbine-canonical
620      * equivalent (probably absolute paths). This is used if the templating
621      * engine (e.g. JSP) does not provide any means to load a page but
622      * the page path is passed to the servlet container.
623      *
624      * @param templatePaths An array of template paths.
625      * @return An array of translated template paths.
626      * @deprecated Each template engine service should know how to translate
627      *             a request onto a file.
628      */
629     @Override
630     @Deprecated
631     public String[] translateTemplatePaths(String[] templatePaths)
632     {
633         for (int i = 0; i < templatePaths.length; i++)
634         {
635             templatePaths[i] = servletService.getRealPath(templatePaths[i]);
636         }
637         return templatePaths;
638     }
639 
640     /**
641      * Delegates to the appropriate {@link
642      * org.apache.turbine.services.template.TemplateEngineService} to
643      * check the existence of the specified template.
644      *
645      * @param template The template to check for the existence of.
646      * @param templatePaths The paths to check for the template.
647      * @deprecated Use templateExists from the various Templating Engines
648      */
649     @Override
650     @Deprecated
651     public boolean templateExists(String template, String[] templatePaths)
652     {
653         for (String templatePath : templatePaths)
654         {
655             if (new File(templatePath, template).exists())
656             {
657                 return true;
658             }
659         }
660         return false;
661     }
662 
663     /**
664      * Registers the provided template engine for use by the
665      * <code>TemplateService</code>.
666      *
667      * @param service The <code>TemplateEngineService</code> to register.
668      */
669     @Override
670     public void registerTemplateEngineService(TemplateEngineService service)
671     {
672         String[] exts = service.getAssociatedFileExtensions();
673 
674         for (String ext : exts)
675         {
676             templateEngineRegistry.put(ext, service);
677         }
678     }
679 
680     /**
681      * The {@link org.apache.turbine.services.template.TemplateEngineService}
682      * associated with the specified template's file extension.
683      *
684      * @param template The template name.
685      * @return The template engine service.
686      */
687     @Override
688     public TemplateEngineService getTemplateEngineService(String template)
689     {
690         return templateEngineRegistry.get(getExtension(template));
691     }
692 
693     /**
694      * Register a template Mapper to the service. This Mapper
695      * performs the template mapping and searching for a specific
696      * object type which is managed by the TemplateService.
697      *
698      * @param templateKey  One of the _KEY constants for the Template object types.
699      * @param mapper  An object which implements the Mapper interface.
700      */
701     private void registerMapper(int templateKey, Mapper mapper)
702     {
703         mapper.init();
704         mapperRegistry[templateKey] = mapper;
705     }
706 
707     /**
708      * Load and configure the Template mappers for
709      * the Template Service.
710      *
711      * @param conf The current configuration object.
712      * @throws InitializationException A problem occurred trying to set up the mappers.
713      */
714     @SuppressWarnings("unchecked")
715     private void initMapper(Configuration conf)
716             throws InitializationException
717     {
718         // Create a registry with the number of Template Types managed by this service.
719         // We could use a List object here and extend the number of managed objects
720         // dynamically. However, by using an Object Array, we get much more performance
721         // out of the Template Service.
722         mapperRegistry = new Mapper[TEMPLATE_TYPES];
723 
724         String [] mapperNames = new String [] {
725             Page.NAME, Screen.NAME, Layout.NAME, Navigation.NAME,
726             LAYOUT_TEMPLATE_NAME, SCREEN_TEMPLATE_NAME, NAVIGATION_TEMPLATE_NAME
727         };
728 
729         Class<?> [] mapperKeys = new Class<?> [] {
730             Page.class, Screen.class, Layout.class, Navigation.class,
731             Layout.class, Screen.class, Navigation.class
732         };
733 
734         String [] mapperClasses = new String [] {
735             DirectMapper.class.getName(),
736             ClassMapper.class.getName(),
737             ClassMapper.class.getName(),
738             ClassMapper.class.getName(),
739             LayoutTemplateMapper.class.getName(),
740             ScreenTemplateMapper.class.getName(),
741             DirectTemplateMapper.class.getName()
742         };
743 
744         AssemblerBrokerService../org/apache/turbine/services/assemblerbroker/AssemblerBrokerService.html#AssemblerBrokerService">AssemblerBrokerService ab = (AssemblerBrokerService)TurbineServices.getInstance()
745                                         .getService(AssemblerBrokerService.SERVICE_NAME);
746 
747         int [] mapperCacheSize = new int [mapperKeys.length];
748         Loader<? extends Assembler> [] mapperLoader = new Loader<?>[mapperKeys.length];
749 
750         for (int i = 0; i < mapperKeys.length; i++)
751         {
752             mapperLoader[i] = ab.getLoader((Class<? extends Assembler>)mapperKeys[i]);
753             mapperCacheSize[i] = (mapperLoader[i] != null) ? mapperLoader[i].getCacheSize() : 0;
754         }
755 
756         // HACK: to achieve the same behavior as before
757         mapperLoader[LAYOUT_TEMPLATE_KEY] = null;
758         mapperLoader[SCREEN_TEMPLATE_KEY] = null;
759         mapperLoader[NAVIGATION_TEMPLATE_KEY] = null;
760 
761         String [] mapperDefaultProperty = new String [] {
762             TemplateEngineService.DEFAULT_PAGE,
763             TemplateEngineService.DEFAULT_SCREEN,
764             TemplateEngineService.DEFAULT_LAYOUT,
765             TemplateEngineService.DEFAULT_NAVIGATION,
766             TemplateEngineService.DEFAULT_LAYOUT_TEMPLATE,
767             TemplateEngineService.DEFAULT_SCREEN_TEMPLATE,
768             TemplateEngineService.DEFAULT_NAVIGATION_TEMPLATE
769         };
770 
771         char [] mapperSeparator = new char [] { '.', '.', '.', '.', '/', '/', '/' };
772 
773         String [] mapperPrefix = new String [] {
774             null, null, null, null,
775             Layout.PREFIX,
776             Screen.PREFIX,
777             Navigation.PREFIX  };
778 
779         for (int i = 0; i < TEMPLATE_TYPES; i++)
780         {
781             StringBuilder mapperProperty = new StringBuilder();
782             mapperProperty.append("mapper.");
783             mapperProperty.append(mapperNames[i]);
784             mapperProperty.append(".class");
785 
786             String mapperClass =
787                     conf.getString(mapperProperty.toString(), mapperClasses[i]);
788 
789             log.info("Using {} to map {} elements", mapperClass, mapperNames[i]);
790 
791             Mapper tm = null;
792 
793             try
794             {
795     		    FactoryService factory = (FactoryService)TurbineServices.getInstance().getService(FactoryService.ROLE);
796     		    tm = factory.getInstance(mapperClass);
797             }
798             catch (FactoryException e)
799             {
800         		throw new InitializationException("", e);
801 		    }
802 
803             tm.setUseCache(useCache);
804             tm.setCacheSize(mapperCacheSize[i]);
805             tm.setDefaultProperty(mapperDefaultProperty[i]);
806             tm.setSeparator(mapperSeparator[i]);
807 
808             if (mapperLoader[i] != null && tm instanceof ClassMapper)
809             {
810                 ((ClassMapper) tm).setLoader(mapperLoader[i]);
811             }
812 
813             if (mapperPrefix[i] != null && tm instanceof BaseTemplateMapper)
814             {
815                 ((BaseTemplateMapper) tm).setPrefix(mapperPrefix[i]);
816             }
817 
818             registerMapper(i, tm);
819         }
820     }
821 }