帆软报表设计器源代码。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

308 lines
14 KiB

package com.fr.design.data.datapane.preview.sql;
import com.fr.base.Parameter;
import com.fr.base.ParameterHelper;
import com.fr.base.ParameterMapNameSpace;
import com.fr.data.impl.DBTableData;
import com.fr.data.impl.EscapeSqlHelper;
import com.fr.data.operator.DataOperator;
import com.fr.decision.webservice.v10.config.ConfigService;
import com.fr.design.dialog.DialogActionAdapter;
import com.fr.design.dialog.link.MessageWithLink;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.LocaleLinkProvider;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.parameter.ParameterInputPane;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.general.GeneralContext;
import com.fr.log.FineLoggerFactory;
import com.fr.plugin.injectable.PluginModule;
import com.fr.script.Calculator;
import com.fr.stable.ArrayUtils;
import com.fr.stable.ParameterProvider;
import com.fr.stable.StringUtils;
import com.fr.stable.fun.TableDataProvider;
import com.fr.stable.plugin.ExtraClassManagerProvider;
import com.fr.stable.script.NameSpace;
import javax.swing.BorderFactory;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultHighlighter;
import javax.swing.text.Highlighter;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Frame;
import java.awt.datatransfer.StringSelection;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
public class PreviewPerformedSqlPane extends JDialog implements ActionListener {
private JPanel topPanel;
private JPanel centerPanel;
private JPanel bottomPanel;
private UILabel imageLabel;
/**
* 云中心防止sql注入帮助文档链接在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY = "Fine-Design_Basic_Sql_Injection_Prevention_Help";
/**
* 云中心防止sql注入帮助文档默认链接在配置文件中对应的配置文件key
*/
private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design_Basic_Sql_Injection_Prevention_Help_Default";
public PreviewPerformedSqlPane(Frame frame, String sql) {
this(frame, sql, null, null, false);
}
public PreviewPerformedSqlPane(Frame frame, String sql, List<int[]> selectedSpecialCharIndex, String[] selectedSpecialChar, boolean highlight) {
super(frame, true);
// 提示信息
topPanel = FRGUIPaneFactory.createBorderLayout_L_Pane();
JPanel imagePanel = new JPanel();
JPanel messagePanel;
if (isShowSpecialCharSqlPane(selectedSpecialCharIndex)) {
imageLabel = new UILabel(UIManager.getIcon("OptionPane.warningIcon"));
messagePanel = new JPanel();
messagePanel.setLayout(FRGUIPaneFactory.createBorderLayout());
messagePanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 0, 0));
// 日韩取消超链,直接显示文字
if (isNotShowLink()) {
JLabel label = new JLabel(Toolkit.i18nText("Fine-Design_Basic_Preview_Performed_Sql_Message") + Toolkit.i18nText("Fine-Design_Basic_Sql_Injection_Prevention") + Toolkit.i18nText("Fine-Design_Basic_Preview_Special_Char_Sql_Back_Message"));
messagePanel.add(label);
} else {
MessageWithLink message = new MessageWithLink(Toolkit.i18nText("Fine-Design_Basic_Preview_Special_Char_Sql_Front_Message"), Toolkit.i18nText("Fine-Design_Basic_Sql_Injection_Prevention"), LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT), Toolkit.i18nText("Fine-Design_Basic_Preview_Special_Char_Sql_Back_Message"));
messagePanel.add(message);
}
// 提示图标
JPanel tipPanel = FRGUIPaneFactory.createBorderLayout_L_Pane();
UILabel tipLabel = new UILabel(UIManager.getIcon("OptionPane.tipIcon"));
StringBuilder textBuilder = new StringBuilder();
textBuilder.append("<html>").append(Toolkit.i18nText("Fine-Design_Basic_Processed_Special_Char")).append("<br/>");
for (String sChar : selectedSpecialChar) {
textBuilder.append(sChar).append("<br/>");
}
textBuilder.append("</html>");
tipLabel.setToolTipText(textBuilder.toString());
tipPanel.add(tipLabel, BorderLayout.SOUTH);
topPanel.add(tipPanel, BorderLayout.EAST);
} else {
imageLabel = new UILabel(UIManager.getIcon("OptionPane.informationIcon"));
messagePanel = FRGUIPaneFactory.createVerticalFlowLayout_S_Pane(true);
JLabel label = new JLabel(Toolkit.i18nText("Fine-Design_Basic_Preview_Performed_Sql_Message"));
messagePanel.add(label);
}
imagePanel.add(imageLabel);
topPanel.add(imagePanel, BorderLayout.WEST);
topPanel.add(messagePanel, BorderLayout.CENTER);
topPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 0, 10));
//中间的SQL面板
centerPanel = FRGUIPaneFactory.createBorderLayout_L_Pane();
centerPanel.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
JScrollPane scrollPane = new JScrollPane();
JTextArea checkArea = new JTextArea(sql);
checkArea.setEditable(false);
checkArea.setCursor(new Cursor(Cursor.TEXT_CURSOR));
if (highlight) {
Highlighter highLighter = checkArea.getHighlighter();
DefaultHighlighter.DefaultHighlightPainter p = new DefaultHighlighter.DefaultHighlightPainter(Color.ORANGE);
for (int[] specialCharIndex : selectedSpecialCharIndex) {
try {
highLighter.addHighlight(specialCharIndex[0], specialCharIndex[1], p);
} catch (BadLocationException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
}
scrollPane.setViewportView(checkArea);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
centerPanel.add(scrollPane);
//底部的按钮面板
UIButton okButton = new UIButton(Toolkit.i18nText("Fine-Design_Report_OK"));
okButton.addActionListener(this);
bottomPanel = FRGUIPaneFactory.createBorderLayout_L_Pane();
bottomPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
bottomPanel.add(okButton, BorderLayout.EAST);
this.setTitle(Toolkit.i18nText("Fine-Design_Basic_Preview_Performed_Sql"));
this.setResizable(false);
this.add(topPanel, BorderLayout.NORTH);
this.add(centerPanel, BorderLayout.CENTER);
this.add(bottomPanel, BorderLayout.SOUTH);
this.setSize(600, 400);
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
close();
}
});
GUICoreUtils.centerWindow(this);
}
private boolean isNotShowLink() {
return GeneralContext.getLocale().equals(Locale.JAPAN) || GeneralContext.getLocale().equals(Locale.KOREA);
}
public static void previewPerformedSql(DBTableData tableData) {
Calculator calculator = Calculator.createCalculator();
//参数
ParameterProvider[] parameters = DataOperator.getInstance().getTableDataParameters(tableData);
if (ArrayUtils.isEmpty(parameters)) {
parameters = tableData.getParameters(calculator);
}
Map<String, Object> parameterMap = new HashMap<>();
if (needInputParams(parameters)) {
showParaWindow(parameterMap, parameters);
} else {
for (ParameterProvider parameter : parameters) {
parameterMap.put(parameter.getName(), parameter.getValue());
}
}
for (ParameterProvider parameter : DataOperator.getInstance().getTableDataParameters(tableData)) {
if (parameterMap.containsKey(parameter.getName())) {
parameter.setValue(parameterMap.get(parameter.getName()));
}
}
String sql;
// 计算高亮文本位置
List<int[]> specialCharParamIndex = null;
boolean highlight = true;
NameSpace ns = ParameterMapNameSpace.create(parameterMap);
calculator.pushNameSpace(ns);
Parameter[] paras = processParameters(tableData, calculator);
// 所有被转义参数的集合
refreshEscapeSqlHelper();
Set<String> specialCharParam = EscapeSqlHelper.getInstance().getSpecialCharParam(paras);
// 将参数转义等
Set<TableDataProvider> tableDataProviders = getTableDataProviders();
for (TableDataProvider provider : tableDataProviders) {
provider.processParametersBeforeAnalyzeSQL(paras, calculator);
}
if (!specialCharParam.isEmpty()) {
specialCharParamIndex = ParameterHelper.analyzeCurrentContextTableData4Template(tableData.getQuery(), paras, specialCharParam);
}
String oldSql = ParameterHelper.analyzeCurrentContextTableData4Templatee(tableData.getQuery(), paras);
sql = processExtraSQL(paras, oldSql, calculator, tableDataProviders);
if (!StringUtils.equals(oldSql, sql)) {
highlight = false;
}
// sql内容复制到剪切板
StringSelection selection = new StringSelection(sql);
java.awt.Toolkit.getDefaultToolkit().getSystemClipboard().setContents(selection, selection);
// 弹窗
if (isShowSpecialCharSqlPane(specialCharParamIndex)) {
showSpecialCharSqlPane(sql, specialCharParamIndex, highlight);
} else {
showNormalPreviewPane(sql);
}
}
// 埋点方法
private static void showNormalPreviewPane(String sql) {
PreviewPerformedSqlPane pane = new PreviewPerformedSqlPane(DesignerContext.getDesignerFrame(), sql);
pane.setVisible(true);
}
// 埋点方法
private static void showSpecialCharSqlPane(String sql, List<int[]> specialCharParamIndex, boolean highlight) {
PreviewPerformedSqlPane pane = new PreviewPerformedSqlPane(DesignerContext.getDesignerFrame(), sql, specialCharParamIndex, ConfigService.getInstance().getPSIConfig().getSelectedSpecialChar(), highlight);
pane.setVisible(true);
}
private static void refreshEscapeSqlHelper() {
EscapeSqlHelper.getInstance().setUseForbidWord(ConfigService.getInstance().getPSIConfig().isUseForbidWord());
EscapeSqlHelper.getInstance().setSelectedForbidWord(ConfigService.getInstance().getPSIConfig().getSelectedForbidWord());
EscapeSqlHelper.getInstance().setUseEscapeSpecialChar(ConfigService.getInstance().getPSIConfig().isUseEscapeSpecialChar());
EscapeSqlHelper.getInstance().setSelectedSpecialChar(ConfigService.getInstance().getPSIConfig().getSelectedSpecialChar());
}
private static boolean isShowSpecialCharSqlPane(List<int[]> specialCharParamIndex) {
return specialCharParamIndex != null && !specialCharParamIndex.isEmpty();
}
private static Parameter[] processParameters(DBTableData tableData, Calculator calculator) {
ParameterProvider[] parameters = tableData.getParameters();
if (parameters == null || parameters.length == 0) {
tableData.setParameters(ParameterHelper.analyze4Parameters(tableData.getQueryWithoutComments(), false));
return new Parameter[0];
}
return Parameter.providers2Parameter(Calculator.processParameters(calculator, parameters));
}
private static String processExtraSQL(Parameter[] ps, String sql, Calculator ca, Set<TableDataProvider> tableDataProviders) {
for (TableDataProvider provider : tableDataProviders) {
String newSql = provider.processTableDataSQL(ps, sql, ca);
if (StringUtils.isNotEmpty(newSql)) {
sql = newSql;
}
}
return sql;
}
private static boolean needInputParams(ParameterProvider[] parameters) {
if (ArrayUtils.isNotEmpty(parameters)) {
return true;
}
for (ParameterProvider parameter : parameters) {
if (parameter.getValue() == null || StringUtils.EMPTY.equals(parameter.getValue())) {
return true;
}
}
return false;
}
private static void showParaWindow(final Map<String, Object> parameterMap, ParameterProvider[] inParameters) {
final ParameterInputPane pPane = new ParameterInputPane(inParameters);
pPane.showSmallWindow(new JFrame(), new DialogActionAdapter() {
@Override
public void doOk() {
parameterMap.putAll(pPane.update());
}
}).setVisible(true);
}
private static Set<TableDataProvider> getTableDataProviders() {
ExtraClassManagerProvider classManagerProvider = PluginModule.getAgent(PluginModule.ExtraCore);
if (classManagerProvider == null) {
return new HashSet<>();
}
return classManagerProvider.getArray(TableDataProvider.XML_TAG, EscapeSqlHelper.getInstance());
}
@Override
public void actionPerformed(ActionEvent e) {
this.dispose();
}
private void close() {
this.dispose();
}
}