Package org.beangle.struts2.view.freemarker

Source Code of org.beangle.struts2.view.freemarker.BeangleFreemarkerManager

/* Copyright c 2005-2012.
* Licensed under GNU  LESSER General Public License, Version 3.
* http://www.gnu.org/licenses
*/
package org.beangle.struts2.view.freemarker;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;

import javax.servlet.ServletContext;

import org.apache.commons.lang.StringUtils;
import org.beangle.commons.collection.CollectUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import freemarker.cache.FileTemplateLoader;
import freemarker.cache.MultiTemplateLoader;
import freemarker.cache.TemplateLoader;
import freemarker.cache.WebappTemplateLoader;
import freemarker.ext.beans.BeansWrapper;
import freemarker.template.ObjectWrapper;
import freemarker.template.TemplateException;

/**
* BeangleFreemarkerManager provide:
* <p>
* <li>Better template loader sequence like class://;file://;file//;webapp://</li>
* <li>Multi freemark properties loading(META-INF/freemarker.properties,freemarker.properties)</li>
* <li>Friendly Collection/Map/Object objectwrapper</li>
*
* @author chaostone
*/
public class BeangleFreemarkerManager extends org.apache.struts2.views.freemarker.FreemarkerManager {

  private final Logger logger = LoggerFactory.getLogger(BeangleFreemarkerManager.class);

  @Override
  protected ObjectWrapper createObjectWrapper(ServletContext servletContext) {
    BeansWrapper wrapper = new BeangleObjectWrapper(altMapWrapper);
    // cacheBeanWrapper should be false in most case.
    wrapper.setUseCache(cacheBeanWrapper);
    return wrapper;
  }

  /**
   * The default template loader is a MultiTemplateLoader which includes
   * BeangleClassTemplateLoader(class://) and a WebappTemplateLoader
   * (webapp://) and FileTemplateLoader(file://) . All template path described
   * in init parameter templatePath or TemplatePlath
   * <p/>
   * The ClassTemplateLoader will resolve fully qualified template includes that begin with a
   * slash. for example /com/company/template/common.ftl
   * <p/>
   * The WebappTemplateLoader attempts to resolve templates relative to the web root folder
   */
  @Override
  protected TemplateLoader createTemplateLoader(ServletContext servletContext, String templatePath) {
    // construct a FileTemplateLoader for the init-param 'TemplatePath'
    String[] paths = StringUtils.split(templatePath, ";");
    List<TemplateLoader> loaders = CollectUtils.newArrayList();
    for (String path : paths) {
      if (path.startsWith("class://")) {
        // substring(7) is intentional as we "reuse" the last slash
        loaders.add(new BeangleClassTemplateLoader(path.substring(7)));
      } else if (path.startsWith("file://")) {
        try {
          loaders.add(new FileTemplateLoader(new File(path)));
        } catch (IOException e) {
          throw new RuntimeException("templatePath: " + path + " cannot be accessed", e);
        }
      } else if (path.startsWith("webapp://")) {
        loaders.add(new WebappTemplateLoader(servletContext, path.substring(8)));
      } else {
        throw new RuntimeException("templatePath: " + path
            + " is not well-formed. Use [class://|file://|webapp://] seperated with ;");
      }

    }
    return new MultiTemplateLoader(loaders.toArray(new TemplateLoader[loaders.size()]));
  }

  /**
   * Load the multi settings from the /META-INF/freemarker.properties and
   * /freemarker.properties file on the classpath
   *
   * @see freemarker.template.Configuration#setSettings for the definition of
   *      valid settings
   */
  @SuppressWarnings("unchecked")
  @Override
  protected void loadSettings(ServletContext servletContext) {
    try {
      Properties properties = new Properties();
      Enumeration<?> em = BeangleFreemarkerManager.class.getClassLoader().getResources(
          "META-INF/freemarker.properties");
      while (em.hasMoreElements()) {
        properties.putAll(getProperties((URL) em.nextElement()));
      }
      em = BeangleFreemarkerManager.class.getClassLoader().getResources("freemarker.properties");
      while (em.hasMoreElements()) {
        properties.putAll(getProperties((URL) em.nextElement()));
      }
      StringBuilder sb = new StringBuilder();
      @SuppressWarnings("rawtypes")
      List keys = CollectUtils.newArrayList(properties.keySet());
      Collections.sort(keys);
      for (Iterator<String> iter = keys.iterator(); iter.hasNext();) {
        String key = iter.next();
        String value = (String) properties.get(key);
        if (key == null) { throw new IOException(
            "init-param without param-name.  Maybe the freemarker.properties is not well-formed?"); }
        if (value == null) { throw new IOException(
            "init-param without param-value.  Maybe the freemarker.properties is not well-formed?"); }
        addSetting(key, value);
        sb.append(StringUtils.leftPad(key, 21)).append(" : ").append(value);
        if (iter.hasNext()) sb.append('\n');
      }
      logger.info("Freemarker properties: ->\n{} ", sb);
    } catch (IOException e) {
      logger.error("Error while loading freemarker.properties", e);
    } catch (TemplateException e) {
      logger.error("Error while setting freemarker.properties", e);
    }
  }

  public void addSetting(String name, String value) throws TemplateException {
    if (name.equals("content_type") || name.equals(INITPARAM_CONTENT_TYPE)) {
      contentType = value;
      config.setCustomAttribute("content_type", value);
    } else {
      super.addSetting(name, value);
    }
  }

  private Properties getProperties(URL url) {
    logger.info("loading {}", url);
    InputStream in = null;
    try {
      in = url.openStream();
      if (in != null) {
        Properties p = new Properties();
        p.load(in);
        return p;
      }
    } catch (IOException e) {
      logger.error("Error while loading " + url, e);
    } finally {
      if (in != null) {
        try {
          in.close();
        } catch (IOException io) {
          logger.warn("Unable to close input stream", io);
        }
      }
    }
    return null;
  }
}
TOP

Related Classes of org.beangle.struts2.view.freemarker.BeangleFreemarkerManager

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.