package cn.org.rapid_framework.freemarker.loader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
import javax.sql.DataSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.SingleColumnRowMapper;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import cn.org.rapid_framework.freemarker.FreemarkerTemplateException;
import freemarker.cache.TemplateLoader;
/**
* 用于freemarker从数据库装载template文件
*
*
* 属性值配置实例,将生成如下的load sql:
* <pre>
* //select template_content from template where template_name=?
* DataSourceTemplateLoader loader = new DataSourceTemplateLoader();
* loader.setDataSource(ds);
* loader.setTableName("template");
* loader.setTemplateNameColumn("template_name");
* loader.setTemplateContentColumn("template_content");
* loader.setTimestampColumn("last_modified");
* </pre>
*
* mysql的表创建语句:
* <pre>
* CREATE TABLE template (
* id bigint(20) PRIMARY KEY,
* template_name varchar(255) ,
* template_content text ,
* last_modified timestamp
*)
* </pre>
* @author badqiu
*
*/
public class DataSourceTemplateLoader implements TemplateLoader,InitializingBean{
Log log = LogFactory.getLog(DataSourceTemplateLoader.class);
private JdbcTemplate jdbcTemplate;
private String tableName;
private String templateNameColumn;
private String templateContentColumn;
private String timestampColumn;
public void setDataSource(final DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
public void setTemplateNameColumn(String column) {
this.templateNameColumn = column;
}
public void setTemplateContentColumn(String templateContentColumn) {
this.templateContentColumn = templateContentColumn;
}
public void setTimestampColumn(String timestampColumn) {
this.timestampColumn = timestampColumn;
}
public JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
}
public void afterPropertiesSet() throws Exception {
Assert.notNull(jdbcTemplate,"'dataSource' must be not null");
Assert.hasText(tableName,"'tableName' must be not blank");
Assert.hasText(templateNameColumn,"'templateNameColumn' must be not blank");
Assert.hasText(templateContentColumn,"'templateContentColumn' must be not blank");
log.info("Freemarker template load sql:"+getSql(templateContentColumn));
}
public Object findTemplateSource(final String name) throws IOException {
int count = getJdbcTemplate().queryForInt(getSql("count(*)"),new Object[]{name});
return count > 0 ? name : null;
}
private String getSql(String columnNames) {
return "select "+columnNames+" from "+tableName+" where "+templateNameColumn+"=?";
}
public Reader getReader(Object templateSource, final String encoding) throws IOException {
final String templateName = (String)templateSource;
return (Reader)getJdbcTemplate().query(getSql(templateContentColumn),new Object[]{templateName}, new ResultSetExtractor() {
public Reader extractData(ResultSet rs) throws SQLException,DataAccessException {
while(rs.next()) {
try {
Object obj = rs.getObject(templateContentColumn);
if(obj instanceof String) {
return new StringReader((String)obj);
}else if(obj instanceof Clob) {
return new StringReader(rs.getString(templateContentColumn));
}else if(obj instanceof InputStream) {
return new InputStreamReader((InputStream)obj,encoding);
}else if(obj instanceof Blob) {
return new InputStreamReader(rs.getBinaryStream(templateContentColumn),encoding);
}else {
throw new FreemarkerTemplateException("error sql type of templateContentColumn:"+templateContentColumn);
}
} catch (UnsupportedEncodingException e) {
throw new FreemarkerTemplateException("load template from dataSource with templateName:"+templateName+" occer UnsupportedEncodingException",e);
}
}
throw new FreemarkerTemplateException("not found template from dataSource with templateName:"+templateName);
}
});
}
public long getLastModified(Object templateSource) {
if(StringUtils.hasText(timestampColumn)) {
String templateName = (String)templateSource;
Object timestamp = getJdbcTemplate().queryForObject(getSql(timestampColumn),new Object[]{templateName},new SingleColumnRowMapper());
if(timestamp instanceof Number) {
return ((Number)timestamp).longValue();
}else if(timestamp instanceof Date) {
return ((Date)timestamp).getTime();
}else {
throw new FreemarkerTemplateException("error template timestamp column type,must be Date or Number type");
}
}
return -1;
}
public void closeTemplateSource(Object templateSource) throws IOException {
}
}