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