package de.superx.bin.fm; import java.io.IOException; import java.io.StringWriter; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import java.util.Map; import javax.sql.DataSource; import org.apache.log4j.Logger; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.ResultSetExtractor; import org.springframework.jdbc.support.rowset.SqlRowSet; import de.superx.common.TemplateProcessor.SqlVarType; import de.superx.servlet.SuperXManager; import freemarker.core.Environment; import freemarker.template.ObjectWrapper; import freemarker.template.Template; import freemarker.template.TemplateDirectiveBody; import freemarker.template.TemplateDirectiveModel; import freemarker.template.TemplateException; import freemarker.template.TemplateModel; import freemarker.template.TemplateModelException; public class SqlVarsDirective implements TemplateDirectiveModel { /** * sqlvar "datatypes" * * @author nnguyen, j.hientzsch :) * */ private static Logger logger = Logger.getLogger(SqlVarsDirective.class); private static final String PARAM_VAR_NAME = "name"; private static final String PARAM_VAR_TYPE = "type"; private static final boolean PARSE_FTL = true; private static final String FTL_ENCODING = "UTF-8"; @Override public void execute(Environment env, @SuppressWarnings("rawtypes") Map params, TemplateModel[] loopvars, TemplateDirectiveBody body) throws TemplateException, IOException { // default inclusion of templates up for debate includeTemplates(env); SqlVarType varType = params.get(PARAM_VAR_TYPE) != null ? SqlVarType.valueOf(params.get(PARAM_VAR_TYPE).toString().trim().toLowerCase()) : SqlVarType.none; if (!params.containsKey(PARAM_VAR_NAME)) { throw new TemplateModelException("No variable name is set for sqlvar"); } String varName = params.get(PARAM_VAR_NAME).toString(); String query = ""; ObjectWrapper objWrapper = env.getConfiguration().getObjectWrapper(); if (body != null) { StringWriter bodyContent = new StringWriter(); body.render(bodyContent); query = bodyContent.toString(); } else { logger.warn("Sqlvar " + varName + " has no nested content and therefore no effect and can be removed!"); } JdbcTemplate jt = new JdbcTemplate(); DataSource dataSource = SuperXManager.getBean("dataSource", DataSource.class); jt.setDataSource(dataSource); Object result = null; switch (varType) { case none: case list: { ArrayList list = buildList(jt, query); result = list.size() == 1 ? list.get(0) : list; result = result == null ? "" : result; } break; case hash: case hashlist: { FMListe list = new FMListe(); list = buildHashList(jt, query); result = list.size() == 1 ? list.get(0) : list; } break; case hashsequence: { FMListe list = new FMListe(); list = buildHashList(jt, query); result = list; } break; case sicht: throw new SqlVarsDirectiveException( "SqlVar type sicht is not supported as a freemarker directive instead use in block parsed by de.superx.common.TemplateProcessor"); case sichtsequence: throw new SqlVarsDirectiveException( "SqlVar type sichtsequence is not supported as a freemarker directive instead use in block parsed by de.superx.common.TemplateProcessor"); case string: result = query; break; default: throw new SqlVarsDirectiveException("Unknown SqlVar type " + varType.toString()); } env.setVariable(varName, objWrapper.wrap(result)); } /** * Executes query and and places result as SqlVarType.list into out * * @param jt * @param query * @param out */ private static ArrayList buildList(JdbcTemplate jt, String query) { ArrayList out = new ArrayList<>(); SqlRowSet queryResult = jt.queryForRowSet(query); if (queryResult.first()) { do { out.add(queryResult.getObject(1)); } while (queryResult.next()); }else { out.add(""); //In case the query does not return a result, freemarker needs an empty string for further conditionals } return out; } /** * Executes SQL query and puts result into out as SqlVarType.hashlist * * @param jt * @param query * @param objWrapper * @param out */ private static FMListe buildHashList(JdbcTemplate jt, String query) { FMListe out = new FMListe(); jt.query(query, new ResultSetExtractor() { @Override public Void extractData(ResultSet rs) throws SQLException, DataAccessException { ResultSetMetaData metaData = rs.getMetaData(); int columnCount = metaData.getColumnCount(); List columnNames = new ArrayList<>(columnCount); for (int i = 1; i <= columnCount; i++) { columnNames.add(metaData.getColumnLabel(i)); } while (rs.next()) { SxHash row = new SxHash(); for (String columnName : columnNames) { row.put(columnName, rs.getString(columnName) == null ? "" : rs.getString(columnName)); } out.add(row); } return null; } }); return out; } private static void includeTemplates(Environment env) { Template inclTemplate1 = null, inclTemplate2 = null; try { inclTemplate1 = env.getTemplateForInclusion("SuperX_general", FTL_ENCODING, PARSE_FTL); inclTemplate2 = env.getTemplateForInclusion("SQL_lingua_franca", FTL_ENCODING, PARSE_FTL); } catch (IOException e) { logger.error( "Freemarker template inclusion failed for templates SuperX_general and/or SQL_lingua_franca!\n", e); } if (inclTemplate1 != null && inclTemplate2 != null) { try { env.include(inclTemplate1); env.include(inclTemplate2); } catch (TemplateException e) { logger.warn("Template inclusion failed in SqlVarsDirective:\n" + e.getStackTrace()); } catch (IOException e) { logger.warn("Template inclusion failed in SqlVarsDirective:\n" + e.getStackTrace()); } } } }