org.beangle.struts2.view.freemarker.BeangleFreemarkerManager.java Source code

Java tutorial

Introduction

Here is the source code for org.beangle.struts2.view.freemarker.BeangleFreemarkerManager.java

Source

/* 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;
    }
}