View Javadoc

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