    001package org.apache.turbine.services.template;
    002
    003
    004/*
    005 * Licensed to the Apache Software Foundation (ASF) under one
    006 * or more contributor license agreements.  See the NOTICE file
    007 * distributed with this work for additional information
    008 * regarding copyright ownership.  The ASF licenses this file
    009 * to you under the Apache License, Version 2.0 (the
    010 * "License"); you may not use this file except in compliance
    011 * with the License.  You may obtain a copy of the License at
    012 *
    013 *   http://www.apache.org/licenses/LICENSE-2.0
    014 *
    015 * Unless required by applicable law or agreed to in writing,
    016 * software distributed under the License is distributed on an
    017 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    018 * KIND, either express or implied.  See the License for the
    019 * specific language governing permissions and limitations
    020 * under the License.
    021 */
    022
    023
    024import java.io.File;
    025import java.util.concurrent.ConcurrentHashMap;
    026import java.util.concurrent.ConcurrentMap;
    027
    028import org.apache.commons.configuration.Configuration;
    029import org.apache.commons.lang.StringUtils;
    030import org.apache.commons.logging.Log;
    031import org.apache.commons.logging.LogFactory;
    032import org.apache.fulcrum.factory.FactoryException;
    033import org.apache.fulcrum.factory.FactoryService;
    034import org.apache.fulcrum.parser.ParameterParser;
    035import org.apache.turbine.Turbine;
    036import org.apache.turbine.TurbineConstants;
    037import org.apache.turbine.modules.Assembler;
    038import org.apache.turbine.modules.Layout;
    039import org.apache.turbine.modules.Loader;
    040import org.apache.turbine.modules.Navigation;
    041import org.apache.turbine.modules.Page;
    042import org.apache.turbine.modules.Screen;
    043import org.apache.turbine.pipeline.PipelineData;
    044import org.apache.turbine.services.InitializationException;
    045import org.apache.turbine.services.TurbineBaseService;
    046import org.apache.turbine.services.TurbineServices;
    047import org.apache.turbine.services.assemblerbroker.AssemblerBrokerService;
    048import org.apache.turbine.services.servlet.ServletService;
    049import org.apache.turbine.services.template.mapper.BaseTemplateMapper;
    050import org.apache.turbine.services.template.mapper.ClassMapper;
    051import org.apache.turbine.services.template.mapper.DirectMapper;
    052import org.apache.turbine.services.template.mapper.DirectTemplateMapper;
    053import org.apache.turbine.services.template.mapper.LayoutTemplateMapper;
    054import org.apache.turbine.services.template.mapper.Mapper;
    055import org.apache.turbine.services.template.mapper.ScreenTemplateMapper;
    056import org.apache.turbine.util.uri.URIConstants;
    057
    058/**
    059 * This service provides a method for mapping templates to their
    060 * appropriate Screens or Navigations.  It also allows templates to
    061 * define a layout/navigations/screen modularization within the
    062 * template structure.  It also performs caching if turned on in the
    063 * properties file.
    064 *
    065 * This service is not bound to a specific templating engine but we
    066 * will use the Velocity templating engine for the examples. It is
    067 * available by using the VelocityService.
    068 *
    069 * This assumes the following properties in the Turbine configuration:
    070 *
    071 * <pre>
    072 * # Register the VelocityService for the "vm" extension.
    073 * services.VelocityService.template.extension=vm
    074 *
    075 * # Default Java class for rendering a Page in this service
    076 * # (must be found on the class path (org.apache.turbine.modules.page.VelocityPage))
    077 * services.VelocityService.default.page = VelocityPage
    078 *
    079 * # Default Java class for rendering a Screen in this service
    080 * # (must be found on the class path (org.apache.turbine.modules.screen.VelocityScreen))
    081 * services.VelocityService.default.screen=VelocityScreen
    082 *
    083 * # Default Java class for rendering a Layout in this service
    084 * # (must be found on the class path (org.apache.turbine.modules.layout.VelocityOnlyLayout))
    085 * services.VelocityService.default.layout = VelocityOnlyLayout
    086 *
    087 * # Default Java class for rendering a Navigation in this service
    088 * # (must be found on the class path (org.apache.turbine.modules.navigation.VelocityNavigation))
    089 * services.VelocityService.default.navigation=VelocityNavigation
    090 *
    091 * # Default Template Name to be used as Layout. If nothing else is
    092 * # found, return this as the default name for a layout
    093 * services.VelocityService.default.layout.template = Default.vm
    094 * </pre>
    095 * If you want to render a template, a search path is used to find
    096 * a Java class which might provide information for the context of
    097 * this template.
    098 *
    099 * 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 */
    180public 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}