Package org.apache.tapestry.services.impl

Source Code of org.apache.tapestry.services.impl.TemplateSourceImpl

/* $$ Clover has instrumented this file $$ */// Copyright 2004 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package org.apache.tapestry.services.impl;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.logging.Log;
import org.apache.hivemind.ApplicationRuntimeException;
import org.apache.hivemind.Resource;
import org.apache.tapestry.IAsset;
import org.apache.tapestry.IComponent;
import org.apache.tapestry.IRequestCycle;
import org.apache.tapestry.Tapestry;
import org.apache.tapestry.engine.DefaultComponentPropertySource;
import org.apache.tapestry.engine.IPropertySource;
import org.apache.tapestry.engine.ITemplateSourceDelegate;
import org.apache.tapestry.event.ResetEventListener;
import org.apache.tapestry.parse.ComponentTemplate;
import org.apache.tapestry.parse.ITemplateParserDelegate;
import org.apache.tapestry.parse.TemplateParseException;
import org.apache.tapestry.parse.ITemplateParser;
import org.apache.tapestry.parse.TemplateToken;
import org.apache.tapestry.resolver.ComponentSpecificationResolver;
import org.apache.tapestry.resource.ContextResource;
import org.apache.tapestry.services.TemplateSource;
import org.apache.tapestry.spec.IComponentSpecification;
import org.apache.tapestry.util.MultiKey;

/**
* Implementation of {@link org.apache.tapestry.services.TemplateSource}
* Templates, once parsed,
* stay in memory until explicitly cleared.
*
*
* @author Howard Lewis Ship
*/

public class TemplateSourceImpl implements TemplateSource, ResetEventListener
{public static com.cortexeb.tools.clover.d __CLOVER_338_0 = com.cortexeb.tools.clover.aq.getRecorder(new char[] {67,58,92,119,111,114,107,115,112,97,99,101,92,106,97,107,97,114,116,97,45,116,97,112,101,115,116,114,121,92,102,114,97,109,101,119,111,114,107,92,116,97,114,103,101,116,92,99,108,111,118,101,114,45,100,98},1096998272901L);
    private Log _log;

    // The name of the component/application/etc property that will be used to
    // determine the encoding to use when loading the template

    public static final String TEMPLATE_ENCODING_PROPERTY_NAME =
        "org.apache.tapestry.template-encoding";

    // Cache of previously retrieved templates.  Key is a multi-key of
    // specification resource path and locale (local may be null), value
    // is the ComponentTemplate.

    private Map _cache = Collections.synchronizedMap(new HashMap());

    // Previously read templates; key is the Resource, value
    // is the ComponentTemplate.

    private Map _templates = Collections.synchronizedMap(new HashMap());

    private static final int BUFFER_SIZE = 2000;

    private ITemplateParser _parser;

    /** @since 2.2 */

    private Resource _applicationRoot;

    /** @since 3.0 */

    private ITemplateSourceDelegate _delegate;

    /** @since 3.1 */

    private IPropertySource _applicationPropertySource;

    /** @since 3.1 */

    private ServletContext _context;

    /** @since 3.1 */

    private HttpServletRequest _request;

    /** @since 3.1 */

    private ComponentSpecificationResolver _componentSpecificationResolver;

    public void initializeService()
    {try { __CLOVER_338_0.M[1642]++;
        __CLOVER_338_0.S[7563]++;String servletPath = _request.getServletPath();

        __CLOVER_338_0.S[7564]++;_applicationRoot = new ContextResource(_context, servletPath);
    } finally { }}

    /**
     *  Clears the template cache.  This is used during debugging.
     *
     */

    public void resetEventDidOccur()
    {try { __CLOVER_338_0.M[1643]++;
        __CLOVER_338_0.S[7565]++;_cache.clear();
        __CLOVER_338_0.S[7566]++;_templates.clear();
    } finally { }}

    /**
     *  Reads the template for the component.
     *
     *
     */

    public ComponentTemplate getTemplate(IRequestCycle cycle, IComponent component)
    {try { __CLOVER_338_0.M[1644]++;
        __CLOVER_338_0.S[7567]++;IComponentSpecification specification = component.getSpecification();
        __CLOVER_338_0.S[7568]++;Resource resource = specification.getSpecificationLocation();

        __CLOVER_338_0.S[7569]++;Locale locale = component.getPage().getLocale();

        __CLOVER_338_0.S[7570]++;Object key = new MultiKey(new Object[] { resource, locale }, false);

        __CLOVER_338_0.S[7571]++;ComponentTemplate result = searchCache(key);
        __CLOVER_338_0.S[7572]++;if ((((result != null) && (++__CLOVER_338_0.CT[1304] != 0)) || (++__CLOVER_338_0.CF[1304] == 0))){
            __CLOVER_338_0.S[7573]++;return result;}

        __CLOVER_338_0.S[7574]++;result = findTemplate(cycle, resource, component, locale);

        __CLOVER_338_0.S[7575]++;if ((((result == null) && (++__CLOVER_338_0.CT[1305] != 0)) || (++__CLOVER_338_0.CF[1305] == 0))){
        {
            __CLOVER_338_0.S[7576]++;result = _delegate.findTemplate(cycle, component, locale);

            __CLOVER_338_0.S[7577]++;if ((((result != null) && (++__CLOVER_338_0.CT[1306] != 0)) || (++__CLOVER_338_0.CF[1306] == 0))){
                __CLOVER_338_0.S[7578]++;return result;}

            __CLOVER_338_0.S[7579]++;String message =
                (((component.getSpecification().isPageSpecification()
                    ) && (++__CLOVER_338_0.CT[1307] != 0)) || (++__CLOVER_338_0.CF[1307] == 0))? ImplMessages.noTemplateForPage(component.getExtendedId(), locale)
                    : ImplMessages.noTemplateForComponent(component.getExtendedId(), locale);

            __CLOVER_338_0.S[7580]++;throw new ApplicationRuntimeException(
                message,
                component,
                component.getLocation(),
                null);
        }}

        __CLOVER_338_0.S[7581]++;saveToCache(key, result);

        __CLOVER_338_0.S[7582]++;return result;
    } finally { }}

    private ComponentTemplate searchCache(Object key)
    {try { __CLOVER_338_0.M[1645]++;
        __CLOVER_338_0.S[7583]++;return (ComponentTemplate) _cache.get(key);
    } finally { }}

    private void saveToCache(Object key, ComponentTemplate template)
    {try { __CLOVER_338_0.M[1646]++;
        __CLOVER_338_0.S[7584]++;_cache.put(key, template);

    } finally { }}

    /**
     *  Finds the template for the given component, using the following rules:
     *  <ul>
     <li>If the component has a $template asset, use that
     *  <li>Look for a template in the same folder as the component
     *  <li>If a page in the application namespace, search in the application root
     *  <li>Fail!
     *  </ul>
     *
     *  @return the template, or null if not found
     *
     */

    private ComponentTemplate findTemplate(
        IRequestCycle cycle,
        Resource resource,
        IComponent component,
        Locale locale)
    {try { __CLOVER_338_0.M[1647]++;
        __CLOVER_338_0.S[7585]++;IAsset templateAsset = component.getAsset(TEMPLATE_ASSET_NAME);

        __CLOVER_338_0.S[7586]++;if ((((templateAsset != null) && (++__CLOVER_338_0.CT[1308] != 0)) || (++__CLOVER_338_0.CF[1308] == 0))){
            __CLOVER_338_0.S[7587]++;return readTemplateFromAsset(cycle, component, templateAsset);}

        __CLOVER_338_0.S[7588]++;String name = resource.getName();
        __CLOVER_338_0.S[7589]++;int dotx = name.lastIndexOf('.');
        __CLOVER_338_0.S[7590]++;String templateBaseName = name.substring(0, dotx + 1) + getTemplateExtension(component);

        __CLOVER_338_0.S[7591]++;ComponentTemplate result =
            findStandardTemplate(cycle, resource, component, templateBaseName, locale);

        __CLOVER_338_0.S[7592]++;if ((((result == null
            && component.getSpecification().isPageSpecification()
            && component.getNamespace().isApplicationNamespace()) && (++__CLOVER_338_0.CT[1309] != 0)) || (++__CLOVER_338_0.CF[1309] == 0))){
            __CLOVER_338_0.S[7593]++;result = findPageTemplateInApplicationRoot(cycle, component, templateBaseName, locale);}

        __CLOVER_338_0.S[7594]++;return result;
    } finally { }}

    private ComponentTemplate findPageTemplateInApplicationRoot(
        IRequestCycle cycle,
        IComponent component,
        String templateBaseName,
        Locale locale)
    {try { __CLOVER_338_0.M[1648]++;
        __CLOVER_338_0.S[7595]++;if ((((_log.isDebugEnabled()) && (++__CLOVER_338_0.CT[1310] != 0)) || (++__CLOVER_338_0.CF[1310] == 0))){
            __CLOVER_338_0.S[7596]++;_log.debug("Checking for " + templateBaseName + " in application root");}

        __CLOVER_338_0.S[7597]++;Resource baseLocation = _applicationRoot.getRelativeResource(templateBaseName);
        __CLOVER_338_0.S[7598]++;Resource localizedLocation = baseLocation.getLocalization(locale);

        __CLOVER_338_0.S[7599]++;if ((((localizedLocation == null) && (++__CLOVER_338_0.CT[1311] != 0)) || (++__CLOVER_338_0.CF[1311] == 0))){
            __CLOVER_338_0.S[7600]++;return null;}

        __CLOVER_338_0.S[7601]++;return getOrParseTemplate(cycle, localizedLocation, component);
    } finally { }}

    /**
     *  Reads an asset to get the template.
     *
     */

    private ComponentTemplate readTemplateFromAsset(
        IRequestCycle cycle,
        IComponent component,
        IAsset asset)
    {try { __CLOVER_338_0.M[1649]++;
        __CLOVER_338_0.S[7602]++;InputStream stream = asset.getResourceAsStream(cycle);

        __CLOVER_338_0.S[7603]++;char[] templateData = null;

        __CLOVER_338_0.S[7604]++;try
        {
            __CLOVER_338_0.S[7605]++;String encoding = getTemplateEncoding(component, null);

            __CLOVER_338_0.S[7606]++;templateData = readTemplateStream(stream, encoding);

            __CLOVER_338_0.S[7607]++;stream.close();
        }
        catch (IOException ex)
        {
            __CLOVER_338_0.S[7608]++;throw new ApplicationRuntimeException(ImplMessages.unableToReadTemplate(asset), ex);
        }

        __CLOVER_338_0.S[7609]++;Resource resourceLocation = asset.getResourceLocation();

        __CLOVER_338_0.S[7610]++;return constructTemplateInstance(cycle, templateData, resourceLocation, component);
    } finally { }}

    /**
     *  Search for the template corresponding to the resource and the locale.
     *  This may be in the template map already, or may involve reading and
     *  parsing the template.
     *
     *  @return the template, or null if not found.
     *
     */

    private ComponentTemplate findStandardTemplate(
        IRequestCycle cycle,
        Resource resource,
        IComponent component,
        String templateBaseName,
        Locale locale)
    {try { __CLOVER_338_0.M[1650]++;
        __CLOVER_338_0.S[7611]++;if ((((_log.isDebugEnabled()) && (++__CLOVER_338_0.CT[1312] != 0)) || (++__CLOVER_338_0.CF[1312] == 0))){
            __CLOVER_338_0.S[7612]++;_log.debug(
                "Searching for localized version of template for "
                    + resource
                    + " in locale "
                    + locale.getDisplayName());}

        __CLOVER_338_0.S[7613]++;Resource baseTemplateLocation = resource.getRelativeResource(templateBaseName);

        __CLOVER_338_0.S[7614]++;Resource localizedTemplateLocation = baseTemplateLocation.getLocalization(locale);

        __CLOVER_338_0.S[7615]++;if ((((localizedTemplateLocation == null) && (++__CLOVER_338_0.CT[1313] != 0)) || (++__CLOVER_338_0.CF[1313] == 0))){
            __CLOVER_338_0.S[7616]++;return null;}

        __CLOVER_338_0.S[7617]++;return getOrParseTemplate(cycle, localizedTemplateLocation, component);

    } finally { }}

    /**
     *  Returns a previously parsed template at the specified location (which must already
     *  be localized).  If not already in the template Map, then the
     *  location is parsed and stored into the templates Map, then returned.
     *
     */

    private ComponentTemplate getOrParseTemplate(
        IRequestCycle cycle,
        Resource resource,
        IComponent component)
    {try { __CLOVER_338_0.M[1651]++;

        __CLOVER_338_0.S[7618]++;ComponentTemplate result = (ComponentTemplate) _templates.get(resource);
        __CLOVER_338_0.S[7619]++;if ((((result != null) && (++__CLOVER_338_0.CT[1314] != 0)) || (++__CLOVER_338_0.CF[1314] == 0))){
            __CLOVER_338_0.S[7620]++;return result;}

        // Ok, see if it exists.

        __CLOVER_338_0.S[7621]++;result = parseTemplate(cycle, resource, component);

        __CLOVER_338_0.S[7622]++;if ((((result != null) && (++__CLOVER_338_0.CT[1315] != 0)) || (++__CLOVER_338_0.CF[1315] == 0))){
            __CLOVER_338_0.S[7623]++;_templates.put(resource, result);}

        __CLOVER_338_0.S[7624]++;return result;
    } finally { }}

    /**
     *  Reads the template for the given resource; returns null if the
     *  resource doesn't exist.  Note that this method is only invoked
     *  from a synchronized block, so there shouldn't be threading
     *  issues here.
     *
     */

    private ComponentTemplate parseTemplate(
        IRequestCycle cycle,
        Resource resource,
        IComponent component)
    {try { __CLOVER_338_0.M[1652]++;
        __CLOVER_338_0.S[7625]++;String encoding = getTemplateEncoding(component, resource.getLocale());

        __CLOVER_338_0.S[7626]++;char[] templateData = readTemplate(resource, encoding);
        __CLOVER_338_0.S[7627]++;if ((((templateData == null) && (++__CLOVER_338_0.CT[1316] != 0)) || (++__CLOVER_338_0.CF[1316] == 0))){
            __CLOVER_338_0.S[7628]++;return null;}

        __CLOVER_338_0.S[7629]++;return constructTemplateInstance(cycle, templateData, resource, component);
    } finally { }}

    /**
     *  This method is currently synchronized, because
     *  {@link TemplateParser} is not threadsafe.  Another good candidate
     *  for a pooling mechanism, especially because parsing a template
     *  may take a while.
     *
     */

    private synchronized ComponentTemplate constructTemplateInstance(
        IRequestCycle cycle,
        char[] templateData,
        Resource resource,
        IComponent component)
    {try { __CLOVER_338_0.M[1653]++;
        __CLOVER_338_0.S[7630]++;ITemplateParserDelegate delegate =
            new DefaultParserDelegate(component, cycle, _componentSpecificationResolver);

        __CLOVER_338_0.S[7631]++;TemplateToken[] tokens;

        __CLOVER_338_0.S[7632]++;try
        {
            __CLOVER_338_0.S[7633]++;tokens = _parser.parse(templateData, delegate, resource);
        }
        catch (TemplateParseException ex)
        {
            __CLOVER_338_0.S[7634]++;throw new ApplicationRuntimeException(ImplMessages.unableToParseTemplate(resource), ex);
        }

        __CLOVER_338_0.S[7635]++;if ((((_log.isDebugEnabled()) && (++__CLOVER_338_0.CT[1317] != 0)) || (++__CLOVER_338_0.CF[1317] == 0))){
            __CLOVER_338_0.S[7636]++;_log.debug("Parsed " + tokens.length + " tokens from template");}

        __CLOVER_338_0.S[7637]++;return new ComponentTemplate(templateData, tokens);
    } finally { }}

    /**
     *  Reads the template, given the complete path to the
     *  resource.  Returns null if the resource doesn't exist.
     *
     */

    private char[] readTemplate(Resource resource, String encoding)
    {try { __CLOVER_338_0.M[1654]++;
        __CLOVER_338_0.S[7638]++;if ((((_log.isDebugEnabled()) && (++__CLOVER_338_0.CT[1318] != 0)) || (++__CLOVER_338_0.CF[1318] == 0))){
            __CLOVER_338_0.S[7639]++;_log.debug("Reading template " + resource);}

        __CLOVER_338_0.S[7640]++;URL url = resource.getResourceURL();

        __CLOVER_338_0.S[7641]++;if ((((url == null) && (++__CLOVER_338_0.CT[1319] != 0)) || (++__CLOVER_338_0.CF[1319] == 0))){
        {
            __CLOVER_338_0.S[7642]++;if ((((_log.isDebugEnabled()) && (++__CLOVER_338_0.CT[1320] != 0)) || (++__CLOVER_338_0.CF[1320] == 0))){
                __CLOVER_338_0.S[7643]++;_log.debug("Template does not exist.");}

            __CLOVER_338_0.S[7644]++;return null;
        }}

        __CLOVER_338_0.S[7645]++;if ((((_log.isDebugEnabled()) && (++__CLOVER_338_0.CT[1321] != 0)) || (++__CLOVER_338_0.CF[1321] == 0))){
            __CLOVER_338_0.S[7646]++;_log.debug("Reading template from URL " + url);}

        __CLOVER_338_0.S[7647]++;InputStream stream = null;

        __CLOVER_338_0.S[7648]++;try
        {
            __CLOVER_338_0.S[7649]++;stream = url.openStream();

            __CLOVER_338_0.S[7650]++;return readTemplateStream(stream, encoding);
        }
        catch (IOException ex)
        {
            __CLOVER_338_0.S[7651]++;throw new ApplicationRuntimeException(ImplMessages.unableToReadTemplate(resource), ex);
        }
        finally
        {
            __CLOVER_338_0.S[7652]++;Tapestry.close(stream);
        }

    } finally { }}

    /**
     *  Reads a Stream into memory as an array of characters.
     *
     */

    private char[] readTemplateStream(InputStream stream, String encoding) throws IOException
    {try { __CLOVER_338_0.M[1655]++;
        __CLOVER_338_0.S[7653]++;char[] charBuffer = new char[BUFFER_SIZE];
        __CLOVER_338_0.S[7654]++;StringBuffer buffer = new StringBuffer();

        __CLOVER_338_0.S[7655]++;InputStreamReader reader;
        __CLOVER_338_0.S[7656]++;if ((((encoding != null) && (++__CLOVER_338_0.CT[1322] != 0)) || (++__CLOVER_338_0.CF[1322] == 0))){
            __CLOVER_338_0.S[7657]++;reader = new InputStreamReader(new BufferedInputStream(stream), encoding);}
        else{
            __CLOVER_338_0.S[7658]++;reader = new InputStreamReader(new BufferedInputStream(stream));}

        __CLOVER_338_0.S[7659]++;try
        {
            __CLOVER_338_0.S[7660]++;while (true){
            {
                __CLOVER_338_0.S[7661]++;int charsRead = reader.read(charBuffer, 0, BUFFER_SIZE);

                __CLOVER_338_0.S[7662]++;if ((((charsRead <= 0) && (++__CLOVER_338_0.CT[1323] != 0)) || (++__CLOVER_338_0.CF[1323] == 0))){
                    __CLOVER_338_0.S[7663]++;break;}

                __CLOVER_338_0.S[7664]++;buffer.append(charBuffer, 0, charsRead);
            }}
        }
        finally
        {
            __CLOVER_338_0.S[7665]++;reader.close();
        }

        // OK, now reuse the charBuffer variable to
        // produce the final result.

        __CLOVER_338_0.S[7666]++;int length = buffer.length();

        __CLOVER_338_0.S[7667]++;charBuffer = new char[length];

        // Copy the character out of the StringBuffer and into the
        // array.

        __CLOVER_338_0.S[7668]++;buffer.getChars(0, length, charBuffer, 0);

        __CLOVER_338_0.S[7669]++;return charBuffer;
    } finally { }}

    /**
     *  Checks for the {@link Tapestry#TEMPLATE_EXTENSION_PROPERTY} in the component's
     *  specification, then in the component's namespace's specification.  Returns
     *  {@link Tapestry#DEFAULT_TEMPLATE_EXTENSION} if not otherwise overriden.
     *
     */

    private String getTemplateExtension(IComponent component)
    {try { __CLOVER_338_0.M[1656]++;
        __CLOVER_338_0.S[7670]++;String extension =
            component.getSpecification().getProperty(Tapestry.TEMPLATE_EXTENSION_PROPERTY);

        __CLOVER_338_0.S[7671]++;if ((((extension != null) && (++__CLOVER_338_0.CT[1324] != 0)) || (++__CLOVER_338_0.CF[1324] == 0))){
            __CLOVER_338_0.S[7672]++;return extension;}

        __CLOVER_338_0.S[7673]++;extension =
            component.getNamespace().getSpecification().getProperty(
                Tapestry.TEMPLATE_EXTENSION_PROPERTY);

        __CLOVER_338_0.S[7674]++;if ((((extension != null) && (++__CLOVER_338_0.CT[1325] != 0)) || (++__CLOVER_338_0.CF[1325] == 0))){
            __CLOVER_338_0.S[7675]++;return extension;}

        __CLOVER_338_0.S[7676]++;return Tapestry.DEFAULT_TEMPLATE_EXTENSION;
    } finally { }}

    private String getTemplateEncoding(IComponent component, Locale locale)
    {try { __CLOVER_338_0.M[1657]++;
        __CLOVER_338_0.S[7677]++;IPropertySource source =
            new DefaultComponentPropertySource(component, _applicationPropertySource, locale);

        __CLOVER_338_0.S[7678]++;return source.getPropertyValue(TEMPLATE_ENCODING_PROPERTY_NAME);
    } finally { }}

    /** @since 3.1 */

    public void setParser(ITemplateParser parser)
    {try { __CLOVER_338_0.M[1658]++;
        __CLOVER_338_0.S[7679]++;_parser = parser;
    } finally { }}

    /** @since 3.1 */

    public void setApplicationPropertySource(IPropertySource source)
    {try { __CLOVER_338_0.M[1659]++;
        __CLOVER_338_0.S[7680]++;_applicationPropertySource = source;
    } finally { }}

    /** @since 3.1 */

    public void setLog(Log log)
    {try { __CLOVER_338_0.M[1660]++;
        __CLOVER_338_0.S[7681]++;_log = log;
    } finally { }}

    /** @since 3.1 */

    public void setDelegate(ITemplateSourceDelegate delegate)
    {try { __CLOVER_338_0.M[1661]++;
        __CLOVER_338_0.S[7682]++;_delegate = delegate;
    } finally { }}

    /** @since 3.1 */

    public void setContext(ServletContext context)
    {try { __CLOVER_338_0.M[1662]++;
        __CLOVER_338_0.S[7683]++;_context = context;
    } finally { }}

    /** @since 3.1 */

    public void setRequest(HttpServletRequest request)
    {try { __CLOVER_338_0.M[1663]++;
        __CLOVER_338_0.S[7684]++;_request = request;
    } finally { }}

    /** @since 3.1 */

    public void setComponentSpecificationResolver(ComponentSpecificationResolver resolver)
    {try { __CLOVER_338_0.M[1664]++;
        __CLOVER_338_0.S[7685]++;_componentSpecificationResolver = resolver;
    } finally { }}

}
TOP

Related Classes of org.apache.tapestry.services.impl.TemplateSourceImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.