package com.norteksoft.mms.base.utils;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Locale;
import java.util.Map;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.jsp.PageContext;
import org.apache.struts2.ServletActionContext;
import freemarker.cache.StringTemplateLoader;
import freemarker.ext.jsp.TaglibFactory;
import freemarker.ext.servlet.AllHttpScopesHashModel;
import freemarker.ext.servlet.HttpRequestHashModel;
import freemarker.ext.servlet.HttpRequestParametersHashModel;
import freemarker.ext.servlet.HttpSessionHashModel;
import freemarker.ext.servlet.IncludePage;
import freemarker.ext.servlet.ServletContextHashModel;
import freemarker.template.Configuration;
import freemarker.template.ObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateModel;
public class FremarkParseUtils {
private static final String KEY_JSP_TAGLIBS = "JspTaglibs";
private static final String ATTR_JSP_TAGLIBS_MODEL = ".freemarker.JspTaglibs";
private static final String ATTR_SESSION_MODEL = ".freemarker.Session";
private static final String ATTR_APPLICATION_MODEL = ".freemarker.Application";
private static final String KEY_APPLICATION = "Application";
private static final String KEY_APPLICATION_PRIVATE = "__FreeMarkerServlet.Application__";
private static final String KEY_SESSION = "Session";
private static final String ATTR_REQUEST_MODEL = ".freemarker.Request";
private static final String ATTR_REQUEST_PARAMETERS_MODEL = ".freemarker.RequestParameters";
private static final String KEY_REQUEST = "Request";
private static final String KEY_INCLUDE = "include_page";
private static final String KEY_REQUEST_PRIVATE = "__FreeMarkerServlet.Request__";
private static final String KEY_REQUEST_PARAMETERS = "RequestParameters";
private static TemplateModel createModel(PageContext pageContext,Map<String, Object> map) {
ObjectWrapper wrapper = ObjectWrapper.DEFAULT_WRAPPER;
HttpServletRequest request = (HttpServletRequest)pageContext.getRequest();
HttpServletResponse response = (HttpServletResponse)pageContext.getResponse();
HttpServlet servlete = new ProxyServlet(pageContext.getServletConfig(), pageContext.getServletContext());
ServletContextHashModel servletContextModel = new ServletContextHashModel(servlete, wrapper);
ServletActionContext.getServletContext().setAttribute(ATTR_APPLICATION_MODEL,servletContextModel);
TaglibFactory taglibs = new TaglibFactory(ServletActionContext.getServletContext());
ServletActionContext.getServletContext().setAttribute(ATTR_JSP_TAGLIBS_MODEL,taglibs);
AllHttpScopesHashModel params = new AllHttpScopesHashModel(wrapper, pageContext.getServletContext(), request);
params.putUnlistedModel(KEY_APPLICATION, servletContextModel);
params.putUnlistedModel(KEY_APPLICATION_PRIVATE, servletContextModel);
params.putUnlistedModel(KEY_JSP_TAGLIBS, (TemplateModel)ServletActionContext.getServletContext().getAttribute(ATTR_JSP_TAGLIBS_MODEL));
// Create hash model wrapper for session
HttpSessionHashModel sessionModel;
HttpSession session = request.getSession(false);
sessionModel = (HttpSessionHashModel) session.getAttribute(ATTR_SESSION_MODEL);
if (sessionModel == null ) {
sessionModel = new HttpSessionHashModel(session, wrapper);
session.setAttribute(ATTR_SESSION_MODEL, sessionModel);
}
params.putUnlistedModel(KEY_SESSION, sessionModel);
// Create hash model wrapper for request
HttpRequestHashModel requestModel = (HttpRequestHashModel) request.getAttribute(ATTR_REQUEST_MODEL);
if (requestModel == null || requestModel.getRequest() != request)
{
requestModel = new HttpRequestHashModel(request, response, wrapper);
request.setAttribute(ATTR_REQUEST_MODEL, requestModel);
request.setAttribute(ATTR_REQUEST_PARAMETERS_MODEL,new HttpRequestParametersHashModel(request));
}
params.putUnlistedModel(KEY_REQUEST, requestModel);
params.putUnlistedModel(KEY_INCLUDE, new IncludePage(request, response));
params.putUnlistedModel(KEY_REQUEST_PRIVATE, requestModel);
// Create hash model wrapper for request parameters
HttpRequestParametersHashModel requestParametersModel = (HttpRequestParametersHashModel) request.getAttribute(ATTR_REQUEST_PARAMETERS_MODEL);
params.putUnlistedModel(KEY_REQUEST_PARAMETERS, requestParametersModel);
//将用户数据放入model中
params.putAll(map);
return params;
}
private static Configuration config = null;
static FremarkParseUtils getInstance() {
return new FremarkParseUtils();
}
FremarkParseUtils() {
if (config == null) {
config = new Configuration();
config.setTemplateLoader(new StringTemplateLoader());
try {
config.setSetting("datetime_format", "yyyy-MM-dd HH:mm:ss");
config.setLocale(Locale.CHINA);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
private String render(TemplateModel dataModel, String text) throws Exception {
String ret = null;
BufferedReader reader=null;
StringWriter stringWriter=null;
BufferedWriter writer=null;
try {
reader= new BufferedReader(new StringReader(text));
Template template = new Template(null, reader, config, "UTF-8");
stringWriter= new StringWriter();
writer = new BufferedWriter(stringWriter);
template.process(dataModel, writer);
writer.flush();
ret = stringWriter.toString();
} catch (Exception ex) {
ex.printStackTrace();
ret = null;
}finally{
reader.close();
stringWriter.close();
writer.close();
}
return ret;
}
/**
* 解析fremark模板(模板中可以含jsp标签)
* 模板文件可以向下面例子一样引用jsp标签:
* <#global c=JspTaglibs["http://java.sun.com/jsp/jstl/core"]>
* <#escape x as x?c>
* <@c.out value="测试c标签" ></@c.out>
* 模板使用标签测试中
* </#escape>
*
* @param temlate 模板文件
* @param pageContext
* @param map 用户数据
* @return 解析后的html
* @throws Exception
*/
public static String parseFremarkTemplate(String temlate,PageContext pageContext,Map<String, Object> map) throws Exception {
TemplateModel model = createModel(pageContext,map);
return FremarkParseUtils.getInstance().render(model, temlate);
}
}
/*
* 对servlet的简单实现,用来代理config和context
*/
class ProxyServlet extends HttpServlet{
private static final long serialVersionUID = 1L;
private ServletConfig config;
private ServletContext context;
ProxyServlet(ServletConfig config, ServletContext context){
this.config = config;
this.context = context;
}
@Override
public ServletConfig getServletConfig() {
return config;
}
@Override
public ServletContext getServletContext() {
return context;
}
}