/*
* Copyright 2002-2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openuap.cms.engine.generate.processor;
import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import org.openuap.base.util.StringUtil;
import org.openuap.base.web.mvc.view.BaseClassTemplateLoader;
import org.openuap.cms.config.CMSConfig;
import org.openuap.cms.engine.profile.PublishProfileInfoHolder;
import org.openuap.cms.engine.profile.impl.PublishOperationProfileImpl;
import org.openuap.runtime.plugin.view.freemarker.PluginFreeMarkerConfigurer;
import org.openuap.runtime.setup.BaseApplicationConfiguration;
import org.openuap.runtime.setup.BaseConfigUtil;
import org.openuap.tpl.engine.plugin.FreeMarkerEngineContentFilter;
import org.openuap.tpl.engine.plugin.TplProcessorFilterPluginManager;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import freemarker.cache.FileTemplateLoader;
import freemarker.cache.MultiTemplateLoader;
import freemarker.cache.TemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
/**
* <p>
* FreeMarker模板处理帮助者
* </p>
*
* <p>
* $Id: FreeMarkerTplProcessorHelper.java 3966 2010-12-16 12:10:02Z orangeforjava $
* </p>
*
* @author Joseph
* @version 1.0
*/
public class FreeMarkerTplProcessorHelper {
private PluginFreeMarkerConfigurer freemarkerConfigurer;
private Configuration configuration;
/**
* 处理模板
*
* @param tplContent
* 模板内容
* @param tplName
* 模板名称
* @param model
* 模型
* @param errors
* 错误
* @return 模板处理后的结果
*/
public String processTemplate(String tplContent, String tplName, Map model,
List errors) {
try {
Configuration newConfiguration = this.getConfiguration();
//
String rs = freeMarkerProcess(tplContent, tplName, model,
newConfiguration, errors);
return rs;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public void setFreemarkerConfigurer(
PluginFreeMarkerConfigurer freemarkerConfigurer) {
this.freemarkerConfigurer = freemarkerConfigurer;
}
/**
* 具体处理模板
*
* @param context
* @param configuration
* @param errors
* @return
*/
protected synchronized String freeMarkerProcess(String tplContent,
String tplName, Map model, Configuration configuration, List errors) {
// 性能诊断-start
PublishOperationProfileImpl op = null;
Exception exception = null;
if (PublishProfileInfoHolder.isEnableProfile()) {
op = new PublishOperationProfileImpl();
op.setOperation("FreeMarkerProcessor");
op.setStartTime(System.currentTimeMillis());
}
try {
if (tplContent == null) {
// 模板内容为空,不予处理
return null;
}
// 从字符串构建模板实例
Template template = new Template(tplName, new StringReader(
tplContent), configuration);
//
//
Map<String, Object> inModel = new HashMap<String, Object>();
addContentModel(inModel, model, tplContent, configuration);
//
long s1 = System.currentTimeMillis();
// TODO 影响模板的处理速度因素?
String fileContent = FreeMarkerTemplateUtils
.processTemplateIntoString(template, inModel);
//
//System.out.println("单纯处理模板渲染耗时:"
// + (System.currentTimeMillis() - s1) + "毫秒");
return fileContent;
} catch (Exception ex) {
exception = ex;
ex.printStackTrace();
errors.add(ex);
return null;
} finally {
// 性能诊断-end
if (PublishProfileInfoHolder.isEnableProfile()) {
op.setEndTime(System.currentTimeMillis());
op.setException(exception);
if (exception != null) {
// 若有异常,保存此时的模板内容
op.setTemplateContent(tplContent);
}
PublishProfileInfoHolder.getProfile().addPublishOperation(op);
}
}
}
protected CMSConfig getConfig() {
return CMSConfig.getInstance();
}
/**
* 配置FreeMarker引擎
*
* @param newConfiguration
* @param userTplPath
* @throws IOException
*/
private void settingConfiguration(Configuration newConfiguration,
String userTplPath) throws IOException {
// 1,get the dest template file name.
String rootPath = this.getConfig().getTemplatePath();
String sys_prefix = "/";
String tmp_prefix = "/tmp/";
// 系统模板路径
String sysTplPath = rootPath;
sysTplPath += sys_prefix;
sysTplPath = StringUtil.normalizePath(sysTplPath);
File sysTplDir = new File(sysTplPath);
if (!sysTplDir.exists()) {
sysTplDir.mkdirs();
}
// 临时模板路径
String tmpTplPath = rootPath + tmp_prefix;
tmpTplPath = StringUtil.normalizePath(tmpTplPath);
File tmpTplDir = new File(tmpTplPath);
if (!tmpTplDir.exists()) {
tmpTplDir.mkdirs();
}
// 用户模板路径
File userTplDir = new File(userTplPath);
if (!userTplDir.exists()) {
userTplDir.mkdirs();
}
//
FileTemplateLoader ftl1 = new FileTemplateLoader(sysTplDir);
FileTemplateLoader ftl2 = new FileTemplateLoader(userTplDir);
FileTemplateLoader ftl3 = new FileTemplateLoader(tmpTplDir);
// 设定模板装载路径
// FIX:调整模板装载路径的顺序
TemplateLoader[] loaders = new TemplateLoader[] { ftl3, ftl2, ftl1,
this.freemarkerConfigurer.getTemplateClassLoader(),
new BaseClassTemplateLoader() };
MultiTemplateLoader mtl = new MultiTemplateLoader(loaders);
newConfiguration.setTemplateLoader(mtl);
// 设置模板编码
BaseApplicationConfiguration baseConfig = BaseConfigUtil.getConfig();
String encoding = baseConfig.getString("cms.tpl.encoding", "UTF-8");
//
// 设置系统输入模板编码与内容输出编码
// 系统可以设置模版的编码,这样可以适用于不同的模版编码
// 内容输出的编码与模板编码相同
// 在在线模版编辑器内将采用编码转换统一使用UTF-8来编辑模版
newConfiguration.setDefaultEncoding(encoding);
newConfiguration.setEncoding(Locale.getDefault(), encoding);
newConfiguration.setEncoding(Locale.SIMPLIFIED_CHINESE, encoding);
newConfiguration.setOutputEncoding(encoding);
// 添加模板宏自动输入
addAutoImport(newConfiguration);
//
}
/**
* <p>
* 添加宏输入
* </p>
* TODO 解决多个宏使用同一前缀的问题
*
* @param configuration
*/
protected void addAutoImport(Configuration configuration) {
List<FreeMarkerEngineContentFilter> filters = getContentFilters();
for (FreeMarkerEngineContentFilter filter : filters) {
Map macroMap = filter.getMacroDefinitions();
Set<String> keySet = macroMap.keySet();
for (String key : keySet) {
String value = (String) macroMap.get(key);
value = value.trim();
configuration.addAutoImport(key, value);
}
}
}
/**
* 添加模板处理器的模型数据
*
* @param inModel
* @param model
*/
protected void addContentModel(Map<String, Object> inModel, Map model,
String tplContent, Configuration configuration) {
List<FreeMarkerEngineContentFilter> filters = getContentFilters();
for (FreeMarkerEngineContentFilter filter : filters) {
Map sharedVariableMap = filter.getSharedVariables(tplContent,
model, configuration);
Set<String> keySet = sharedVariableMap.keySet();
for (String key : keySet) {
inModel.put(key, sharedVariableMap.get(key));
}
}
//
inModel.putAll(model);
}
/**
* 取得FreeMarker配置对象
* @return the configuration
*/
public Configuration getConfiguration() {
if (configuration == null) {
try {
configuration = freemarkerConfigurer.createConfiguration();
// 获得用户模板路径
String userTplPath = this.getConfig().getUserTemplatePath();
userTplPath = StringUtil.normalizePath(userTplPath);
// 设置模板引擎配置属性
settingConfiguration(configuration, userTplPath);
} catch (Exception e) {
e.printStackTrace();
}
}
return configuration;
}
/**
*
* @param configuration
*/
public void setConfiguration(Configuration configuration) {
this.configuration = configuration;
}
protected List<FreeMarkerEngineContentFilter> getContentFilters() {
List<FreeMarkerEngineContentFilter> filters = TplProcessorFilterPluginManager
.getContentFilters();
return filters;
}
}