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