Package com.google.sitebricks

Source Code of com.google.sitebricks.TemplateLoader

package com.google.sitebricks;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.util.Arrays;

import javax.servlet.ServletContext;

import net.jcip.annotations.Immutable;

import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.sitebricks.compiler.TemplateCompiler;
import com.google.sitebricks.routing.PageBook;

/**
* @author Dhanji R. Prasanna (dhanji@gmail.com)
*/
@Immutable
public class TemplateLoader {

  private final Provider<ServletContext> context;
  private final TemplateSystem templateSystem;

  @Inject
  public TemplateLoader(Provider<ServletContext> context, TemplateSystem templateSystem) {
    this.context = context;
    this.templateSystem = templateSystem;
  }

  public Renderable compile(PageBook.Page page) {

      Show methodShow = page.getShow();

      Template template = load(page.pageClass(), methodShow);
      TemplateCompiler templateCompiler = templateSystem.compilerFor(template.getName());

      if (templateCompiler == null) {
        templateCompiler = templateSystem.compilerFor("html");
      }

      return templateCompiler.compile(page.pageClass(), template);
    }

  public Renderable compile(Class<?> templateClass) {
      Template template = load(templateClass, null);
      TemplateCompiler templateCompiler = templateSystem.compilerFor(template.getName());
      //
      // This is how the old mechanism worked, for example if dynamic.js comes through the system we still pass back
      // the html compiler. JVZ: not sure why this wouldn't be directly routed to the right resource. TODO: investigate
      //
      if (templateCompiler == null) {
        templateCompiler = templateSystem.compilerFor("html");
      }

      return templateCompiler.compile(templateClass, template);
    }

  // protected for the tests access...
  protected Template load(Class<?> pageClass, Show methodShow) {
    //
    // try to find the template name
    //
    String template = null;
    String extension = null;

    Show show = pageClass.getAnnotation(Show.class);
    if (null != show) {
      template = show.value();
    }
   
    if (methodShow != null) {
        if (template != null) {
            template = template + methodShow.value();
        }
        else {
            template = methodShow.value();
        }
    }

    //
    // an empty string means no template name was given
    //
    if (template == null || template.length() == 0) {
      // use the default name for the page class
      template = pageClass.getSimpleName();
    } else {
      // Check and see if the supplied template value has a supported file extension
      for (String ext : templateSystem.getTemplateExtensions()) {
        String type = ext.replace("%s.", ".");
        if (template.endsWith(type)) {
          extension = type;
          break;
        }
      }
    }

    if (null == template) {
      throw new MissingTemplateException(String.format("Could not determine the base template name for %s", Show.class));
    }

    TemplateSource templateSource = null;
    String text;

    boolean appendExtension = false;
    try {
      final ServletContext servletContext = context.get();
      InputStream stream = null;

      //
      // If there was a matching file extension, short-circuit the deep search
      //

      if (template.contains(".") || null != extension) {
        // Check class neighborhood for direct match
        stream = pageClass.getResourceAsStream(template);

        // Check url conventions for direct match
        if (null == stream) {
          stream = open(template, servletContext);
        }

        // Same as above, but checks in WEB-INF
        if (null == stream) {
          stream = openWebInf(template, servletContext);
        }

        // Finally, try to get the resource from the servlet context internally
        if (null == stream) {
          stream = servletContext.getResourceAsStream(template);
        }
      }

      //
      // No direct match, so start hunting.
      // First, look in class neighborhood for template
      //

      if (null == stream) {
        appendExtension = true;
        for (String ext : templateSystem.getTemplateExtensions()) {
          String name = String.format(ext, template);

          stream = pageClass.getResourceAsStream(name);

          if (null != stream) {
            extension = ext;
            break;
          }
        }
      }

      //
      // Check for qualified file paths in context
      // TODO: I think this is redundant, but make sure before deleting
      //

      if (null == stream) {
        for (String ext : templateSystem.getTemplateExtensions()) {
          String name = String.format(ext, pageClass.getSimpleName());

          stream = open(name, servletContext);

          if (null != stream) {
            extension = ext;
            break;
          }
        }
      }

      //
      // Same thing, but check in WEB-INF
      //

      if (null == stream) {
        for (String ext : templateSystem.getTemplateExtensions()) {
          String name = String.format(ext, pageClass.getSimpleName());

          stream = openWebInf(name, servletContext);

          if (null != stream) {
            extension = ext;
            break;
          }
        }
      }

      //
      // Finally, look in the ServletContext resource path if not in classpath
      //

      if (null == stream) {
        for (String ext : templateSystem.getTemplateExtensions()) {
          String name = String.format(ext, template);

          stream = servletContext.getResourceAsStream(name);

          if (null != stream) {
            extension = ext;
            break;
          }
        }
      }

      //
      //if there's still no template, then error out
      //
      if (null == stream) {
        throw new MissingTemplateException(String.format(
          "Could not find a suitable template for %s, did you remember to place an @Show? None of " +
          Arrays.toString(templateSystem.getTemplateExtensions()).replace("%s.", ".")
          + " could be found in either package [%s], in the root of the resource dir OR in WEB-INF/.",
          pageClass.getName(), pageClass.getSimpleName(), pageClass.getPackage().getName()));
      }

      text = read(stream);
    } catch (IOException e) {
      throw new TemplateLoadingException("Could not load template for (i/o error): " + pageClass, e);
    }

    if (appendExtension)
      template += "." + extension;

    return new Template(template, text, templateSource);
   
  }

  private static InputStream open(String templateName, ServletContext context) {
    try {
      String path = context.getRealPath(templateName);
      return path == null ? null : new FileInputStream(path);
    } catch (FileNotFoundException e) {
      return null;
    }
  }

  private static InputStream openWebInf(String templateName, ServletContext context) {
    return open("/WEB-INF/" + templateName, context);
  }

  private static String read(InputStream stream) throws IOException {
    BufferedReader reader = new BufferedReader(new InputStreamReader(stream, "UTF-8"));

    StringBuilder builder = new StringBuilder();
    try {
      while (reader.ready()) {
        builder.append(reader.readLine());
        builder.append("\n");
      }
    } finally {
      stream.close();
    }

    return builder.toString();
  }
}
TOP

Related Classes of com.google.sitebricks.TemplateLoader

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.