forked from p85126437/datagear
数据集添加防注入和自动转义参数值支持
This commit is contained in:
parent
99160a875c
commit
be9f2904b6
|
@ -3,8 +3,8 @@
|
|||
ok 图表JS对象新增dataSetParamValueFirst、dataSetParamValuesFirst、resetDataSetParamValuesFirst函数;
|
||||
ok 简化图表展示链接为/chart/show/*、看板展示链接为/dashboard/show/*;
|
||||
ok 看板模板新增dashboard、chart函数自动补齐功能;
|
||||
ok 数据集添加防注入和自动转义参数值支持;
|
||||
添加更多内置图表插件:嵌套饼图、盒须图、地图热力图、路径图;
|
||||
数据管理高级查询功能、SQL数据集添加防注入支持;
|
||||
数据集、图表、看板新增复制功能;
|
||||
|
||||
待定:
|
||||
|
|
|
@ -18,11 +18,13 @@ import java.util.Map;
|
|||
import org.apache.commons.csv.CSVFormat;
|
||||
import org.apache.commons.csv.CSVParser;
|
||||
import org.apache.commons.csv.CSVRecord;
|
||||
import org.datagear.analysis.DataSet;
|
||||
import org.datagear.analysis.DataSetException;
|
||||
import org.datagear.analysis.DataSetProperty;
|
||||
import org.datagear.analysis.DataSetQuery;
|
||||
import org.datagear.analysis.ResolvableDataSet;
|
||||
import org.datagear.analysis.ResolvedDataSetResult;
|
||||
import org.datagear.analysis.support.fmk.CsvOutputFormat;
|
||||
import org.datagear.util.IOUtil;
|
||||
|
||||
/**
|
||||
|
@ -33,6 +35,9 @@ import org.datagear.util.IOUtil;
|
|||
*/
|
||||
public abstract class AbstractCsvDataSet extends AbstractResolvableDataSet implements ResolvableDataSet
|
||||
{
|
||||
public static final DataSetFmkTemplateResolver CSV_TEMPLATE_RESOLVER = new DataSetFmkTemplateResolver(
|
||||
CsvOutputFormat.INSTANCE);
|
||||
|
||||
/** 作为名称行的行号 */
|
||||
private int nameRow = -1;
|
||||
|
||||
|
@ -369,4 +374,25 @@ public abstract class AbstractCsvDataSet extends AbstractResolvableDataSet imple
|
|||
{
|
||||
return CSVFormat.DEFAULT.withIgnoreSurroundingSpaces().parse(reader);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将指定CSV文本作为模板解析。
|
||||
* <p>
|
||||
* 注意:即使此数据集没有定义任何参数({@linkplain #hasParam()}为{@code false}),此方法也必须将{@code csv}作为模板解析,因为存在如下应用场景:
|
||||
* 用户不定义数据集参数,但却定义模板内容,之后用户自行在{@linkplain DataSet#getResult(DataSetQuery)}参数映射表中传递模板内容所须的参数值。
|
||||
* </p>
|
||||
*
|
||||
* @param csv
|
||||
* @param query
|
||||
* @return
|
||||
*/
|
||||
protected String resolveCsvAsTemplate(String csv, DataSetQuery query)
|
||||
{
|
||||
if (csv == null)
|
||||
return null;
|
||||
|
||||
Map<String, ?> values = query.getParamValues();
|
||||
|
||||
return CSV_TEMPLATE_RESOLVER.resolve(csv, values);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,8 +33,7 @@ import org.datagear.analysis.ResultDataFormat;
|
|||
*/
|
||||
public abstract class AbstractDataSet extends AbstractIdentifiable implements DataSet
|
||||
{
|
||||
/** 默认Freemarker模板解析器 */
|
||||
public static final DataSetFmkTemplateResolver FMK_TEMPLATE_RESOLVER = new DataSetFmkTemplateResolver();
|
||||
public static final DataSetFmkTemplateResolver GENERAL_TEMPLATE_RESOLVER = new DataSetFmkTemplateResolver();
|
||||
|
||||
private String name;
|
||||
|
||||
|
@ -522,7 +521,7 @@ public abstract class AbstractDataSet extends AbstractIdentifiable implements Da
|
|||
}
|
||||
|
||||
/**
|
||||
* 将指定文本作为Freemarker模板解析。
|
||||
* 将指定文本作为模板解析。
|
||||
* <p>
|
||||
* 注意:即使此数据集没有定义任何参数({@linkplain #hasParam()}为{@code false}),此方法也必须将{@code text}作为模板解析,因为存在如下应用场景:
|
||||
* 用户不定义数据集参数,但却定义模板内容,之后用户自行在{@linkplain DataSet#getResult(DataSetQuery)}参数映射表中传递模板内容所须的参数值。
|
||||
|
@ -532,16 +531,13 @@ public abstract class AbstractDataSet extends AbstractIdentifiable implements Da
|
|||
* @param query
|
||||
* @return
|
||||
*/
|
||||
public String resolveAsFmkTemplate(String text, DataSetQuery query)
|
||||
protected String resolveTextAsTemplate(String text, DataSetQuery query)
|
||||
{
|
||||
// if (!hasParam())
|
||||
// return text;
|
||||
|
||||
if (text == null)
|
||||
return null;
|
||||
|
||||
Map<String, ?> values = query.getParamValues();
|
||||
|
||||
return FMK_TEMPLATE_RESOLVER.resolve(text, values);
|
||||
return GENERAL_TEMPLATE_RESOLVER.resolve(text, values);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,12 +14,14 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.datagear.analysis.DataSet;
|
||||
import org.datagear.analysis.DataSetException;
|
||||
import org.datagear.analysis.DataSetProperty;
|
||||
import org.datagear.analysis.DataSetQuery;
|
||||
import org.datagear.analysis.DataSetResult;
|
||||
import org.datagear.analysis.ResolvableDataSet;
|
||||
import org.datagear.analysis.ResolvedDataSetResult;
|
||||
import org.datagear.analysis.support.fmk.JsonOutputFormat;
|
||||
import org.datagear.util.IOUtil;
|
||||
import org.datagear.util.StringUtil;
|
||||
|
||||
|
@ -41,6 +43,9 @@ import com.jayway.jsonpath.spi.mapper.JacksonMappingProvider;
|
|||
*/
|
||||
public abstract class AbstractJsonDataSet extends AbstractResolvableDataSet implements ResolvableDataSet
|
||||
{
|
||||
public static final DataSetFmkTemplateResolver JSON_TEMPLATE_RESOLVER = new DataSetFmkTemplateResolver(
|
||||
JsonOutputFormat.INSTANCE);
|
||||
|
||||
/** 使用Jackson的{@code JSONPath}配置 */
|
||||
protected static final Configuration JACKSON_JSON_PATH_CONFIGURATION = Configuration.builder()
|
||||
.jsonProvider(new JacksonJsonProvider()).mappingProvider(new JacksonMappingProvider()).build();
|
||||
|
@ -366,4 +371,25 @@ public abstract class AbstractJsonDataSet extends AbstractResolvableDataSet impl
|
|||
{
|
||||
return JsonSupport.getObjectMapperNonStardand();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将指定JSON文本作为模板解析。
|
||||
* <p>
|
||||
* 注意:即使此数据集没有定义任何参数({@linkplain #hasParam()}为{@code false}),此方法也必须将{@code json}作为模板解析,因为存在如下应用场景:
|
||||
* 用户不定义数据集参数,但却定义模板内容,之后用户自行在{@linkplain DataSet#getResult(DataSetQuery)}参数映射表中传递模板内容所须的参数值。
|
||||
* </p>
|
||||
*
|
||||
* @param json
|
||||
* @param query
|
||||
* @return
|
||||
*/
|
||||
protected String resolveJsonAsTemplate(String json, DataSetQuery query)
|
||||
{
|
||||
if (json == null)
|
||||
return null;
|
||||
|
||||
Map<String, ?> values = query.getParamValues();
|
||||
|
||||
return JSON_TEMPLATE_RESOLVER.resolve(json, values);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ public class CsvValueDataSet extends AbstractCsvDataSet
|
|||
@Override
|
||||
protected TemplateResolvedSource<Reader> getCsvReader(DataSetQuery query) throws Throwable
|
||||
{
|
||||
String csv = resolveAsFmkTemplate(this.value, query);
|
||||
String csv = resolveCsvAsTemplate(this.value, query);
|
||||
return new TemplateResolvedSource<>(IOUtil.getReader(csv), csv);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import com.google.common.cache.Cache;
|
|||
import com.google.common.cache.CacheBuilder;
|
||||
|
||||
import freemarker.cache.TemplateLoader;
|
||||
import freemarker.core.OutputFormat;
|
||||
import freemarker.template.Configuration;
|
||||
import freemarker.template.Template;
|
||||
import freemarker.template.TemplateException;
|
||||
|
@ -44,17 +45,26 @@ public class DataSetFmkTemplateResolver implements TemplateResolver
|
|||
|
||||
public DataSetFmkTemplateResolver()
|
||||
{
|
||||
this(1000);
|
||||
this(null, 1000);
|
||||
}
|
||||
|
||||
public DataSetFmkTemplateResolver(int cacheCapacity)
|
||||
public DataSetFmkTemplateResolver(OutputFormat outputFormat)
|
||||
{
|
||||
this(outputFormat, 1000);
|
||||
}
|
||||
|
||||
public DataSetFmkTemplateResolver(OutputFormat outputFormat, int cacheCapacity)
|
||||
{
|
||||
super();
|
||||
this.nameTemplateLoader = new NameTemplateLoader(cacheCapacity);
|
||||
this.configuration = new Configuration(Configuration.VERSION_2_3_30);
|
||||
this.configuration.setTemplateLoader(this.nameTemplateLoader);
|
||||
setDataSetTemplateStandardConfig(this.configuration);
|
||||
this.configuration.setCacheStorage(new freemarker.cache.MruCacheStorage(0, cacheCapacity));
|
||||
|
||||
Configuration configuration = new Configuration(Configuration.VERSION_2_3_30);
|
||||
configuration.setCacheStorage(new freemarker.cache.MruCacheStorage(0, cacheCapacity));
|
||||
|
||||
if (outputFormat != null)
|
||||
configuration.setOutputFormat(outputFormat);
|
||||
|
||||
setConfiguration(configuration);
|
||||
}
|
||||
|
||||
public NameTemplateLoader getNameTemplateLoader()
|
||||
|
@ -78,10 +88,11 @@ public class DataSetFmkTemplateResolver implements TemplateResolver
|
|||
public void setConfiguration(Configuration configuration)
|
||||
{
|
||||
this.configuration = configuration;
|
||||
setDataSetTemplateStandardConfig(this.configuration);
|
||||
|
||||
if (this.nameTemplateLoader != null)
|
||||
this.configuration.setTemplateLoader(this.nameTemplateLoader);
|
||||
|
||||
setDataSetTemplateStandardConfig(this.configuration);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -33,6 +33,7 @@ import org.apache.hc.core5.http.NameValuePair;
|
|||
import org.apache.hc.core5.http.io.HttpClientResponseHandler;
|
||||
import org.apache.hc.core5.http.io.entity.StringEntity;
|
||||
import org.apache.hc.core5.http.message.BasicNameValuePair;
|
||||
import org.datagear.analysis.DataSet;
|
||||
import org.datagear.analysis.DataSetException;
|
||||
import org.datagear.analysis.DataSetProperty;
|
||||
import org.datagear.analysis.DataSetQuery;
|
||||
|
@ -407,17 +408,38 @@ public class HttpDataSet extends AbstractResolvableDataSet
|
|||
|
||||
protected String resolveTemplateUri(DataSetQuery query) throws Throwable
|
||||
{
|
||||
return resolveAsFmkTemplate(this.uri, query);
|
||||
return resolveTextAsTemplate(this.uri, query);
|
||||
}
|
||||
|
||||
protected String resolveTemplateHeaderContent(DataSetQuery query) throws Throwable
|
||||
{
|
||||
return resolveAsFmkTemplate(this.headerContent, query);
|
||||
return resolveJsonAsTemplate(this.headerContent, query);
|
||||
}
|
||||
|
||||
protected String resolveTemplateRequestContent(DataSetQuery query) throws Throwable
|
||||
{
|
||||
return resolveAsFmkTemplate(this.requestContent, query);
|
||||
return resolveJsonAsTemplate(this.requestContent, query);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将指定JSON文本作为模板解析。
|
||||
* <p>
|
||||
* 注意:即使此数据集没有定义任何参数({@linkplain #hasParam()}为{@code false}),此方法也必须将{@code json}作为模板解析,因为存在如下应用场景:
|
||||
* 用户不定义数据集参数,但却定义模板内容,之后用户自行在{@linkplain DataSet#getResult(DataSetQuery)}参数映射表中传递模板内容所须的参数值。
|
||||
* </p>
|
||||
*
|
||||
* @param json
|
||||
* @param query
|
||||
* @return
|
||||
*/
|
||||
protected String resolveJsonAsTemplate(String json, DataSetQuery query)
|
||||
{
|
||||
if (json == null)
|
||||
return null;
|
||||
|
||||
Map<String, ?> values = query.getParamValues();
|
||||
|
||||
return AbstractJsonDataSet.JSON_TEMPLATE_RESOLVER.resolve(json, values);
|
||||
}
|
||||
|
||||
protected ClassicHttpRequest createHttpRequest(String uri) throws Throwable
|
||||
|
|
|
@ -65,7 +65,7 @@ public class JsonValueDataSet extends AbstractJsonDataSet
|
|||
@Override
|
||||
protected TemplateResolvedSource<Reader> getJsonReader(DataSetQuery query) throws Throwable
|
||||
{
|
||||
String json = resolveAsFmkTemplate(this.value, query);
|
||||
String json = resolveJsonAsTemplate(this.value, query);
|
||||
return new TemplateResolvedSource<>(IOUtil.getReader(json), json);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.datagear.analysis.DataSetProperty.DataType;
|
|||
import org.datagear.analysis.DataSetQuery;
|
||||
import org.datagear.analysis.ResolvableDataSet;
|
||||
import org.datagear.analysis.ResolvedDataSetResult;
|
||||
import org.datagear.analysis.support.fmk.SqlOutputFormat;
|
||||
import org.datagear.util.IOUtil;
|
||||
import org.datagear.util.JDBCCompatiblity;
|
||||
import org.datagear.util.JdbcSupport;
|
||||
|
@ -48,6 +49,9 @@ public class SqlDataSet extends AbstractResolvableDataSet implements ResolvableD
|
|||
{
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(SqlDataSet.class);
|
||||
|
||||
public static final DataSetFmkTemplateResolver SQL_TEMPLATE_RESOLVER = new DataSetFmkTemplateResolver(
|
||||
SqlOutputFormat.INSTANCE);
|
||||
|
||||
protected static final JdbcSupport JDBC_SUPPORT = new JdbcSupport();
|
||||
|
||||
private ConnectionFactory connectionFactory;
|
||||
|
@ -105,7 +109,7 @@ public class SqlDataSet extends AbstractResolvableDataSet implements ResolvableD
|
|||
protected TemplateResolvedDataSetResult resolveResult(DataSetQuery query, List<DataSetProperty> properties,
|
||||
boolean resolveProperties) throws DataSetException
|
||||
{
|
||||
String sql = resolveAsFmkTemplate(getSql(), query);
|
||||
String sql = resolveSqlAsTemplate(getSql(), query);
|
||||
|
||||
Connection cn = null;
|
||||
|
||||
|
@ -408,4 +412,25 @@ public class SqlDataSet extends AbstractResolvableDataSet implements ResolvableD
|
|||
{
|
||||
return JDBC_SUPPORT;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将指定SQL文本作为模板解析。
|
||||
* <p>
|
||||
* 注意:即使此数据集没有定义任何参数({@linkplain #hasParam()}为{@code false}),此方法也必须将{@code sql}作为模板解析,因为存在如下应用场景:
|
||||
* 用户不定义数据集参数,但却定义模板内容,之后用户自行在{@linkplain DataSet#getResult(DataSetQuery)}参数映射表中传递模板内容所须的参数值。
|
||||
* </p>
|
||||
*
|
||||
* @param sql
|
||||
* @param query
|
||||
* @return
|
||||
*/
|
||||
protected String resolveSqlAsTemplate(String sql, DataSetQuery query)
|
||||
{
|
||||
if (sql == null)
|
||||
return null;
|
||||
|
||||
Map<String, ?> values = query.getParamValues();
|
||||
|
||||
return SQL_TEMPLATE_RESOLVER.resolve(sql, values);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* Copyright 2018 datagear.tech
|
||||
*
|
||||
* Licensed under the LGPLv3 license:
|
||||
* http://www.gnu.org/licenses/lgpl-3.0.html
|
||||
*/
|
||||
|
||||
package org.datagear.analysis.support.fmk;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
|
||||
import freemarker.core.CommonMarkupOutputFormat;
|
||||
import freemarker.template.TemplateModelException;
|
||||
|
||||
/**
|
||||
* CSV输出格式。
|
||||
* <p>
|
||||
* 此类负责将CSV Freemarker模板中的字符串值转义为合法的SQL字符串。
|
||||
* </p>
|
||||
* <p>
|
||||
* 转义规则如下所示:
|
||||
* </p>
|
||||
* <p>
|
||||
* <table>
|
||||
* <tr>
|
||||
* <td>源字符</td>
|
||||
* <td>转义目标</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>"</td>
|
||||
* <td>""</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>回车</td>
|
||||
* <td>\r</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>换行</td>
|
||||
* <td>\n</td>
|
||||
* </tr>
|
||||
* </table>
|
||||
* </p>
|
||||
*
|
||||
* @author datagear@163.com
|
||||
*
|
||||
*/
|
||||
public class CsvOutputFormat extends CommonMarkupOutputFormat<TemplateCsvOutputModel>
|
||||
{
|
||||
public static final CsvOutputFormat INSTANCE = new CsvOutputFormat();
|
||||
|
||||
protected CsvOutputFormat()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
return "CSV";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMimeType()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void output(String textToEsc, Writer out) throws IOException, TemplateModelException
|
||||
{
|
||||
escapeCsvString(textToEsc, out);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapePlainText(String plainTextContent) throws TemplateModelException
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
try
|
||||
{
|
||||
escapeCsvString(plainTextContent, sb);
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
throw new TemplateModelException(e);
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLegacyBuiltInBypassed(String builtInName) throws TemplateModelException
|
||||
{
|
||||
return builtInName.equals("csv");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TemplateCsvOutputModel newTemplateMarkupOutputModel(String plainTextContent, String markupContent)
|
||||
throws TemplateModelException
|
||||
{
|
||||
return new TemplateCsvOutputModel(plainTextContent, markupContent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转义CSV字符串。
|
||||
*
|
||||
* @param plainText
|
||||
* @param out
|
||||
* @throws IOException
|
||||
*/
|
||||
protected void escapeCsvString(String plainText, Appendable out) throws IOException
|
||||
{
|
||||
char[] cs = plainText.toCharArray();
|
||||
|
||||
for (int i = 0; i < cs.length; i++)
|
||||
{
|
||||
char c = cs[i];
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '"':
|
||||
{
|
||||
out.append('"');
|
||||
out.append('"');
|
||||
break;
|
||||
}
|
||||
case '\r':
|
||||
{
|
||||
out.append('\\');
|
||||
out.append('r');
|
||||
break;
|
||||
}
|
||||
case '\n':
|
||||
{
|
||||
out.append('\\');
|
||||
out.append('n');
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
out.append(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* Copyright 2018 datagear.tech
|
||||
*
|
||||
* Licensed under the LGPLv3 license:
|
||||
* http://www.gnu.org/licenses/lgpl-3.0.html
|
||||
*/
|
||||
|
||||
package org.datagear.analysis.support.fmk;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
|
||||
import freemarker.core.CommonMarkupOutputFormat;
|
||||
import freemarker.template.TemplateModelException;
|
||||
|
||||
/**
|
||||
* JSON输出格式。
|
||||
* <p>
|
||||
* 此类负责将JSON Freemarker模板中的字符串值转义为合法的SQL字符串。
|
||||
* </p>
|
||||
* <p>
|
||||
* 转义规则如下所示:
|
||||
* </p>
|
||||
* <p>
|
||||
* <table>
|
||||
* <tr>
|
||||
* <td>源字符</td>
|
||||
* <td>转义目标</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>"</td>
|
||||
* <td>\"</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>\</td>
|
||||
* <td>\\</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>回车</td>
|
||||
* <td>\r</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>换行</td>
|
||||
* <td>\n</td>
|
||||
* </tr>
|
||||
* </table>
|
||||
* </p>
|
||||
*
|
||||
* @author datagear@163.com
|
||||
*
|
||||
*/
|
||||
public class JsonOutputFormat extends CommonMarkupOutputFormat<TemplateJsonOutputModel>
|
||||
{
|
||||
public static final JsonOutputFormat INSTANCE = new JsonOutputFormat();
|
||||
|
||||
protected JsonOutputFormat()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
return "JSON";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMimeType()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void output(String textToEsc, Writer out) throws IOException, TemplateModelException
|
||||
{
|
||||
escapeJsonString(textToEsc, out);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapePlainText(String plainTextContent) throws TemplateModelException
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
try
|
||||
{
|
||||
escapeJsonString(plainTextContent, sb);
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
throw new TemplateModelException(e);
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLegacyBuiltInBypassed(String builtInName) throws TemplateModelException
|
||||
{
|
||||
return builtInName.equals("json");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TemplateJsonOutputModel newTemplateMarkupOutputModel(String plainTextContent, String markupContent)
|
||||
throws TemplateModelException
|
||||
{
|
||||
return new TemplateJsonOutputModel(plainTextContent, markupContent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转义JSON字符串。
|
||||
*
|
||||
* @param plainText
|
||||
* @param out
|
||||
* @throws IOException
|
||||
*/
|
||||
protected void escapeJsonString(String plainText, Appendable out) throws IOException
|
||||
{
|
||||
char[] cs = plainText.toCharArray();
|
||||
|
||||
for (int i = 0; i < cs.length; i++)
|
||||
{
|
||||
char c = cs[i];
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '"':
|
||||
{
|
||||
out.append('\\');
|
||||
out.append('"');
|
||||
break;
|
||||
}
|
||||
case '\\':
|
||||
{
|
||||
out.append('\\');
|
||||
out.append('\\');
|
||||
break;
|
||||
}
|
||||
case '\r':
|
||||
{
|
||||
out.append('\\');
|
||||
out.append('r');
|
||||
break;
|
||||
}
|
||||
case '\n':
|
||||
{
|
||||
out.append('\\');
|
||||
out.append('n');
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
out.append(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
* Copyright 2018 datagear.tech
|
||||
*
|
||||
* Licensed under the LGPLv3 license:
|
||||
* http://www.gnu.org/licenses/lgpl-3.0.html
|
||||
*/
|
||||
|
||||
package org.datagear.analysis.support.fmk;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
|
||||
import freemarker.core.CommonMarkupOutputFormat;
|
||||
import freemarker.template.TemplateModelException;
|
||||
|
||||
/**
|
||||
* SQL输出格式。
|
||||
* <p>
|
||||
* 此类负责将SQL Freemarker模板中的字符串值转义为合法的SQL字符串。
|
||||
* </p>
|
||||
* <p>
|
||||
* 转义规则如下所示:
|
||||
* </p>
|
||||
* <p>
|
||||
* <table>
|
||||
* <tr>
|
||||
* <td>源字符</td>
|
||||
* <td>转义目标</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>'</td>
|
||||
* <td>''</td>
|
||||
* </tr>
|
||||
* </table>
|
||||
* </p>
|
||||
*
|
||||
* @author datagear@163.com
|
||||
*
|
||||
*/
|
||||
public class SqlOutputFormat extends CommonMarkupOutputFormat<TemplateSqlOutputModel>
|
||||
{
|
||||
public static final SqlOutputFormat INSTANCE = new SqlOutputFormat();
|
||||
|
||||
protected SqlOutputFormat()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
return "SQL";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMimeType()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void output(String textToEsc, Writer out) throws IOException, TemplateModelException
|
||||
{
|
||||
escapeSqlString(textToEsc, out);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapePlainText(String plainTextContent) throws TemplateModelException
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
try
|
||||
{
|
||||
escapeSqlString(plainTextContent, sb);
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
throw new TemplateModelException(e);
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLegacyBuiltInBypassed(String builtInName) throws TemplateModelException
|
||||
{
|
||||
return builtInName.equals("sql");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TemplateSqlOutputModel newTemplateMarkupOutputModel(String plainTextContent, String markupContent)
|
||||
throws TemplateModelException
|
||||
{
|
||||
return new TemplateSqlOutputModel(plainTextContent, markupContent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转义SQL字符串。
|
||||
*
|
||||
* @param plainText
|
||||
* @param out
|
||||
* @throws IOException
|
||||
*/
|
||||
protected void escapeSqlString(String plainText, Appendable out) throws IOException
|
||||
{
|
||||
char[] cs = plainText.toCharArray();
|
||||
|
||||
for (int i = 0; i < cs.length; i++)
|
||||
{
|
||||
char c = cs[i];
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '\'':
|
||||
{
|
||||
out.append('\'');
|
||||
out.append('\'');
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
out.append(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright 2018 datagear.tech
|
||||
*
|
||||
* Licensed under the LGPLv3 license:
|
||||
* http://www.gnu.org/licenses/lgpl-3.0.html
|
||||
*/
|
||||
|
||||
package org.datagear.analysis.support.fmk;
|
||||
|
||||
import freemarker.core.CommonMarkupOutputFormat;
|
||||
import freemarker.core.CommonTemplateMarkupOutputModel;
|
||||
|
||||
/**
|
||||
* CSV输出模型。
|
||||
*
|
||||
* @author datagear@163.com
|
||||
*
|
||||
*/
|
||||
public class TemplateCsvOutputModel extends CommonTemplateMarkupOutputModel<TemplateCsvOutputModel>
|
||||
{
|
||||
public TemplateCsvOutputModel(String plainTextContent, String markupContent)
|
||||
{
|
||||
super(plainTextContent, markupContent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonMarkupOutputFormat<TemplateCsvOutputModel> getOutputFormat()
|
||||
{
|
||||
return CsvOutputFormat.INSTANCE;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright 2018 datagear.tech
|
||||
*
|
||||
* Licensed under the LGPLv3 license:
|
||||
* http://www.gnu.org/licenses/lgpl-3.0.html
|
||||
*/
|
||||
|
||||
package org.datagear.analysis.support.fmk;
|
||||
|
||||
import freemarker.core.CommonMarkupOutputFormat;
|
||||
import freemarker.core.CommonTemplateMarkupOutputModel;
|
||||
|
||||
/**
|
||||
* JSON输出模型。
|
||||
*
|
||||
* @author datagear@163.com
|
||||
*
|
||||
*/
|
||||
public class TemplateJsonOutputModel extends CommonTemplateMarkupOutputModel<TemplateJsonOutputModel>
|
||||
{
|
||||
public TemplateJsonOutputModel(String plainTextContent, String markupContent)
|
||||
{
|
||||
super(plainTextContent, markupContent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonMarkupOutputFormat<TemplateJsonOutputModel> getOutputFormat()
|
||||
{
|
||||
return JsonOutputFormat.INSTANCE;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright 2018 datagear.tech
|
||||
*
|
||||
* Licensed under the LGPLv3 license:
|
||||
* http://www.gnu.org/licenses/lgpl-3.0.html
|
||||
*/
|
||||
|
||||
package org.datagear.analysis.support.fmk;
|
||||
|
||||
import freemarker.core.CommonMarkupOutputFormat;
|
||||
import freemarker.core.CommonTemplateMarkupOutputModel;
|
||||
|
||||
/**
|
||||
* SQL输出模型。
|
||||
*
|
||||
* @author datagear@163.com
|
||||
*
|
||||
*/
|
||||
public class TemplateSqlOutputModel extends CommonTemplateMarkupOutputModel<TemplateSqlOutputModel>
|
||||
{
|
||||
public TemplateSqlOutputModel(String plainTextContent, String markupContent)
|
||||
{
|
||||
super(plainTextContent, markupContent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonMarkupOutputFormat<TemplateSqlOutputModel> getOutputFormat()
|
||||
{
|
||||
return SqlOutputFormat.INSTANCE;
|
||||
}
|
||||
}
|
|
@ -218,7 +218,7 @@ public class CsvFileDataSetEntity extends AbstractCsvFileDataSet implements Dire
|
|||
@Override
|
||||
public String resolveFileNameAsFmkTemplate(String fileName, DataSetQuery query)
|
||||
{
|
||||
return resolveAsFmkTemplate(fileName, query);
|
||||
return resolveTextAsTemplate(fileName, query);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -217,7 +217,7 @@ public class ExcelDataSetEntity extends AbstractExcelDataSet implements Director
|
|||
@Override
|
||||
public String resolveFileNameAsFmkTemplate(String fileName, DataSetQuery query)
|
||||
{
|
||||
return resolveAsFmkTemplate(fileName, query);
|
||||
return resolveTextAsTemplate(fileName, query);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -219,7 +219,7 @@ public class JsonFileDataSetEntity extends AbstractJsonFileDataSet implements Di
|
|||
@Override
|
||||
public String resolveFileNameAsFmkTemplate(String fileName, DataSetQuery query)
|
||||
{
|
||||
return resolveAsFmkTemplate(fileName, query);
|
||||
return resolveTextAsTemplate(fileName, query);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -28,9 +28,7 @@ import org.datagear.analysis.DataSetParam;
|
|||
import org.datagear.analysis.DataSetProperty;
|
||||
import org.datagear.analysis.DataSetQuery;
|
||||
import org.datagear.analysis.ResolvedDataSetResult;
|
||||
import org.datagear.analysis.support.AbstractDataSet;
|
||||
import org.datagear.analysis.support.CsvValueDataSet;
|
||||
import org.datagear.analysis.support.DataSetFmkTemplateResolver;
|
||||
import org.datagear.analysis.support.DataSetParamValueConverter;
|
||||
import org.datagear.analysis.support.JsonValueDataSet;
|
||||
import org.datagear.analysis.support.ProfileDataSet;
|
||||
|
@ -777,7 +775,7 @@ public class DataSetController extends AbstractSchemaConnController
|
|||
public String resolveSql(HttpServletRequest request, HttpServletResponse response,
|
||||
org.springframework.ui.Model springModel, @RequestBody ResolveSqlParam resolveSqlParam) throws Throwable
|
||||
{
|
||||
return resolveFmkSource(resolveSqlParam.getSql(), resolveSqlParam.getParamValues(),
|
||||
return resolveSqlTemplate(resolveSqlParam.getSql(), resolveSqlParam.getParamValues(),
|
||||
resolveSqlParam.getDataSetParams());
|
||||
}
|
||||
|
||||
|
@ -965,15 +963,10 @@ public class DataSetController extends AbstractSchemaConnController
|
|||
return FileUtil.getDirectory(this.tempDirectory, "dataSet", true);
|
||||
}
|
||||
|
||||
protected String resolveFmkSource(String source, Map<String, ?> paramValues, Collection<DataSetParam> dataSetParams)
|
||||
protected String resolveSqlTemplate(String source, Map<String, ?> paramValues, Collection<DataSetParam> dataSetParams)
|
||||
{
|
||||
Map<String, ?> converted = getDataSetParamValueConverter().convert(paramValues, dataSetParams);
|
||||
return getDataSetFmkTemplateResolver().resolve(source, new TemplateContext(converted));
|
||||
}
|
||||
|
||||
protected DataSetFmkTemplateResolver getDataSetFmkTemplateResolver()
|
||||
{
|
||||
return AbstractDataSet.FMK_TEMPLATE_RESOLVER;
|
||||
return SqlDataSet.SQL_TEMPLATE_RESOLVER.resolve(source, new TemplateContext(converted));
|
||||
}
|
||||
|
||||
protected ResponseEntity<OperationMessage> checkSaveSqlDataSetEntity(HttpServletRequest request,
|
||||
|
|
Loading…
Reference in New Issue