Package com.xfltr.hapax

Source Code of com.xfltr.hapax.TemplateCache

package com.xfltr.hapax;

import com.xfltr.hapax.parser.CTemplateParser;
import com.xfltr.hapax.parser.TemplateParser;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.util.HashMap;
import java.util.Map;

/**
* TemplateCache constructs {@link Template} objects based on files stored on
* disk.  TemplateCache implements an in-memory unbounded cache of parsed
* Templates.  Each stored Template is automatically invalidated if the template
* file on disk changes.
*
* See examples/TemplateCacheExample.java for an example of how to use
* TemplateCache.
*
* It is recommended that you place a reference to your TemplateCache instance
* in some globally accessible location so that you use a single cache across
* multiple requests.
*
* @author dcoker
*/
public class TemplateCache implements TemplateLoader {

  private final Map<String, Template> templates_ =
      new HashMap<String, Template>();
  private final Map<String, Long> lastUpdated_ =
      new HashMap<String, Long>();
  private final String basePath_;
  private final TemplateParser parser_;

  /**
   * Creates a TemplateLoader using the CTemplateParser.
   */
  public static TemplateLoader create(String base_path) {
    return new TemplateCache(CTemplateParser.create(), base_path);
  }

  /**
   * Creates a TemplateLoader using the given TemplateParser.
   */
  public static TemplateLoader createForParser(String base_path,
                                               TemplateParser parser) {
    return new TemplateCache(parser, base_path);
  }

  /**
   * Parses and fetches a template from disk.
   *
   * @param filename The path to the template, relative to the templateDirectory
   *                 passed to the ctor of TemplateCache.
   */
  public Template getTemplate(String filename) throws TemplateException {
    filename = PathUtil.join(basePath_, filename);

    // We check the last modified timestamp on the template once per render.
    // If the template has changed, we reload and reparse it.  Otherwise, we
    // return the copy from memory.
    File file = new File(filename);
    long last_modified = file.lastModified();

    if (inCache(filename, last_modified)) {
      return templates_.get(filename);
    }

    FileReader reader;
    try {
      reader = new FileReader(filename);
    } catch (FileNotFoundException e) {
      throw new TemplateException(e);
    }

    String contents;
    try {
      contents = readToString(reader);
    } catch (IOException e) {
      throw new TemplateException(e);
    }

    Template results;
    results = Template.parse(parser_, contents);
    results.setLoaderContext(new TemplateLoaderContext(this, file.getParent()));
    updateCache(filename, results, last_modified);
    return results;
  }

  /**
   * Parses and fetches a template from a subdirectory of the configured
   * basePath. This is useful when fetching templates with paths relative to
   * other templates (such as in includes).
   *
   * TODO: This smells.
   */
  public Template getTemplate(String filename, String templateDirectory)
      throws TemplateException {
    assert templateDirectory.startsWith(basePath_);
    String directory_relative_to_template_directory =
        PathUtil.makeRelative(basePath_, "");
    // Construct the filename that we use in the cache
    filename =
        PathUtil.join(directory_relative_to_template_directory, filename);
    return getTemplate(filename);
  }

  /**
   * Private constructor.
   */
  private TemplateCache(TemplateParser parser, String templateDirectory) {
    this.basePath_ = templateDirectory;
    this.parser_ = parser;
  }

  private String readToString(Reader in) throws IOException {
    StringBuilder buf = new StringBuilder();
    try {
      for (int c = in.read(); -1 != c; c = in.read()) {
        buf.append((char) c);
      }
      return buf.toString();
    } finally {
      in.close();
    }
  }

  private boolean inCache(String filename, long last_modified) {
    return lastUpdated_.containsKey(filename) &&
           lastUpdated_.get(filename) >= last_modified;
  }

  private void updateCache(String filename, Template results,
                           long last_modified) {
    templates_.put(filename, results);
    lastUpdated_.put(filename, last_modified);
  }
}
TOP

Related Classes of com.xfltr.hapax.TemplateCache

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.