package com.palacesun.engine.test;

import bean.Column;
import com.alibaba.druid.DbType;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
import com.alibaba.druid.sql.visitor.SchemaStatVisitor;
import com.alibaba.druid.stat.TableStat;
import com.palacesun.engine.common.ConnectionInformation;
import com.palacesun.engine.common.PreparedStatementInformation;
import com.palacesun.engine.common.ResultSetInformation;
import com.palacesun.engine.common.StatementInformation;
import com.palacesun.engine.event.JdbcEventListener;
import com.palacesun.engine.gateway.EncryptionGatewayManager;
import com.palacesun.engine.gateway.GatewayContext;
import com.palacesun.engine.log.DblogClient;
import com.palacesun.engine.wrapper.ConnectionWrapper;
import com.palacesun.masking.adapter.StringUtils;
import com.palacesun.masking.log.vo.EncryLogVO;
import com.palacesun.masking.tools.EngineUtil;
import com.palacesun.masking.tools.ruleload.RuleLoadUtil;
import com.palacesun.masking.vo.Columninfo;
import com.palacesun.masking.vo.ConnectionInfo;
import com.palacesun.masking.vo.JsonRootBean;
import com.palacesun.masking.vo.TableInfo;
import com.palacesun.masking.vo.masking.MaskingColumnInfo;
import util.SqlUtil;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class TestJdbcEventListener extends JdbcEventListener {
    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    private ResultSetMetaData metaData;

    private volatile String flag = "0";

    protected static Logger logger = Logger.getLogger(TestJdbcEventListener.class.getName());

    public static Map<String, Map<String, String>> ipPortMap = new HashMap<String, Map<String, String>>();

    public static Map<String, Set<Columninfo>> sqlColumSecretKeyMap = new HashMap<String, Set<Columninfo>>();

    public void onBeforeGetConnection(ConnectionInformation connectionInformation) throws ClassNotFoundException {
        if ("0".equals(this.flag))
            try {
                Class.forName("com.palacesun.masking.tools.EngineUtil");
                this.flag = "1";
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
                throw e;
            }
    }

    public void onAfterGetConnection(ConnectionInformation connectionInformation, SQLException e) throws SQLException {
        if (e != null)
            throw e;
    }

    public void onConnectionWrapped(ConnectionInformation connectionInformation) {
    }

    public void onBeforeAddBatch(PreparedStatementInformation statementInformation) {
    }

    public void onAfterAddBatch(PreparedStatementInformation statementInformation, long timeElapsedNanos, SQLException e) {
        statementInformation.context.log();
    }

    public void onAfterAddBatch(StatementInformation statementInformation, long timeElapsedNanos, String sql, SQLException e) {
        statementInformation.context.log();
    }

    public void onBeforeExecute(PreparedStatementInformation statementInformation) {
    }

    public void onAfterExecute(PreparedStatementInformation statementInformation, long timeElapsedNanos, SQLException e) {
        statementInformation.context.log();
    }

    public void onAfterExecute(StatementInformation statementInformation, long timeElapsedNanos, String sql, SQLException e) {
        statementInformation.context.log();
    }

    public void onBeforeExecuteBatch(StatementInformation statementInformation) {
    }

    public void onAfterExecuteBatch(StatementInformation statementInformation, long timeElapsedNanos, int[] updateCounts, SQLException e) {
        statementInformation.context.log();
    }

    public void onBeforeExecuteUpdate(PreparedStatementInformation statementInformation) {
    }

    public void onAfterExecuteUpdate(PreparedStatementInformation statementInformation, long timeElapsedNanos, int rowCount, SQLException e) {
        statementInformation.context.log();
    }

    public void onBeforeExecuteUpdate(StatementInformation statementInformation, String sql) {
    }

    public void onAfterExecuteUpdate(StatementInformation statementInformation, long timeElapsedNanos, String sql, int rowCount, SQLException e) {
        statementInformation.context.log();
    }

    public void onBeforeExecuteQuery(PreparedStatementInformation statementInformation) {
    }

    private String sqlTypeAnalysis(String sql) {
        String[] wordArr = sql.split("\\s+");
        if (wordArr.length > 0)
            return wordArr[0].toUpperCase();
        return "";
    }

    public void onAfterExecuteQuery(PreparedStatementInformation statementInformation, long timeElapsedNanos, SQLException e) {
        statementInformation.context.log();
    }

    public void onAfterExecuteQuery(StatementInformation statementInformation, long timeElapsedNanos, String sql, SQLException e) {
        statementInformation.context.log();
    }

    public void onBeforeAddBatch(StatementInformation statementInformation, String sql) {
        sql = "select * from t_user a";
    }

    public void onBeforeExecute(StatementInformation statementInformation, String sql) {
    }

    public void onBeforeExecuteQuery(StatementInformation statementInformation, String sql) {
    }

    public void onBeforeResultSetNext(ResultSetInformation resultSetInformation) {
    }

    public void onBeforeGetResltSetDate(ResultSet resultSet) throws SQLException {
        try {
            ResultSetMetaData metaData = resultSet.getMetaData();
        } catch (SQLException e) {
            e.printStackTrace();
            throw e;
        }
    }

    public Object onAfterResultSetGet(ResultSetInformation resultSetInformation, String columnLabel, Object value, SQLException e) throws SQLException {
        if (!GatewayContext.isPluginEnabled())
            return value;
        if (value == null || (value instanceof String && StringUtils.isBlank((String) value)))
            return value;
        String encPrefix = EncryptionGatewayManager.getParameterValue("encryption.label");
        if (value.toString().contains(encPrefix) && GatewayContext.isCurrentUserCanSeeDecInfo()) {
            String sqlTemplate = getSqlTemplate(resultSetInformation);
            RuleLoadUtil.writeLog("@@" + value);
            value = getDecData(value, sqlTemplate, columnLabel, encPrefix);
            RuleLoadUtil.writeLog("@@" + value);
        }
        if (!EncryptionGatewayManager.checkParameterFlag("maskingRule"))
            return value;
        int columnIndex = -1;
        String columnName = "";
        String tableName = "";
        String columnType = "";
        try {
            ResultSetMetaData metaData = resultSetInformation.getResultSet().getMetaData();
            int count = metaData.getColumnCount();
            for (int i = 1; i <= count; i++) {
                if (metaData.getColumnLabel(i).equalsIgnoreCase(columnLabel)) {
                    columnIndex = i;
                    columnName = metaData.getColumnLabel(i);
                    columnType = metaData.getColumnTypeName(i);
                    if (columnName == null || "".equals(columnName))
                        columnName = metaData.getColumnName(i);
                    tableName = metaData.getTableName(columnIndex);
                    break;
                }
            }
            if (columnIndex == -1)
                return value;
            if (value == null)
                return value;
            String schema = metaData.getCatalogName(columnIndex);
            if (StringUtils.isEmpty(schema))
                schema = metaData.getSchemaName(columnIndex);
            Connection connection = resultSetInformation.getConnectionInformation().getConnection();
            String urlTemp = connection.getMetaData().getURL();
            Map<String, String> ipAndPortMap = getIpAndPort(urlTemp);
            String ip = ipAndPortMap.get("ip");
            String port = ipAndPortMap.get("port");
            String driverName = resultSetInformation.getConnectionInformation().getConnection().getMetaData().getDriverName();
            String urlDbType = resultSetInformation.getConnectionInformation().getUrl();
            String dbType = "";
            dbType = ConnectionWrapper.getDbType(driverName, urlDbType, dbType);
            if ("oracle".equals(dbType)) {
                int j;
                if (columnType.toLowerCase(Locale.ROOT).contains("char") &&
                        value != null && value instanceof String && !"".equals(value.toString()))
                    value = value.toString().trim();
                schema = connection.getMetaData().getUserName();
                StatementInformation statementInformation = resultSetInformation.getStatementInformation();
                String sqlAll = statementInformation.getSql();
                if (sqlAll.indexOf("-- appUsername=") > 0)
                    sqlAll = sqlAll.substring(0, sqlAll.indexOf("-- appUsername=")).trim();
                if (sqlAll.endsWith(";"))
                    sqlAll = sqlAll.substring(0, sqlAll.length() - 1);
                String[] splitSql = sqlAll.split(";");
                if (splitSql.length == 1) {
                    j = 0;
                } else {
                    for (j = 0; j < splitSql.length; j++) {
                        String trim = splitSql[j].toLowerCase().trim();
                        if (trim.startsWith("select"))
                            break;
                        if (trim.contains("*/")) {
                            int index = trim.indexOf("*/");
                            trim = trim.substring(index + 2).trim();
                            if (trim.startsWith("select"))
                                break;
                        }
                    }
                    if (j == splitSql.length)
                        j = splitSql.length - 1;
                }
                List<Map<String, Object>> sqlParseList = (List<Map<String, Object>>) ConnectionWrapper.sqlParseMap.get(sqlAll);
                if (sqlParseList == null || sqlParseList.isEmpty())
                    sqlParseList = statementInformation.sqlParse;
                if (sqlParseList == null || sqlParseList.isEmpty())
                    return value;
                Map<String, Object> sqlParse = sqlParseList.get(j);
                if (sqlParse != null && !sqlParse.isEmpty()) {
                    List<Column> cols = (List<Column>) sqlParse.get("output-cols");
                    if (cols != null && cols.size() > 0) {
                        List<Column> idxCols = new ArrayList<Column>();
                        for (Column col : cols) {
                            if (col.seq == columnIndex) {
                                String table = col.getTable();
                                if (table == null || table.length() == 0)
                                    continue;
                                String fullname = col.getColumnName();
                                if (fullname == null || fullname.length() == 0)
                                    continue;
                                int idx = fullname.toLowerCase().indexOf(table.toLowerCase());
                                if (idx == -1)
                                    continue;
                                String cname = fullname.substring(idx + table.length() + 1);
                                columnName = cname;
                                tableName = table;
                                schema = col.getSchema();
                            }
                        }
                    }
                }
            } else if ("postgresql".equals(dbType) || "greenplum".equals(dbType) || "gauss".equals(dbType)) {
                String url = connection.getMetaData().getURL();
                if (url.indexOf("searchpath") > 0) {
                    schema = url.substring(url.indexOf("searchpath") + 11);
                } else if (url.indexOf("currentSchema") > 0) {
                    schema = url.substring(url.indexOf("currentSchema") + 14);
                } else {
                    schema = "public";
                }
            } else if ("sql server".equals(dbType)) {
                String url = connection.getMetaData().getURL();
                if (url.indexOf("applicationName") > 0) {
                    schema = url.substring(url.indexOf("applicationName") + "applicationName".length() + 1);
                    if (schema.indexOf(";") != -1)
                        schema = schema.substring(0, schema.indexOf(";"));
                } else {
                    schema = "dbo";
                }
            } else if ("dm".equals(dbType)) {
                String url = resultSetInformation.getConnectionInformation().getUrl();
                if (url.toLowerCase().contains("schema=")) {
                    schema = url.substring(url.toLowerCase().indexOf("schema=") + 7);
                } else {
                    int from = url.indexOf("://");
                    int end = url.indexOf("?");
                    String address = (end == -1) ? url.substring(from + 3) : url.substring(from + 3, end);
                    int idx = address.lastIndexOf("/");
                    schema = address.substring(idx + 1);
                }
            } else if ("db2".equals(dbType)) {
                String url = resultSetInformation.getConnectionInformation().getUrl();
                if (url.contains("currentSchema=")) {
                    schema = url.substring(url.indexOf("currentSchema=") + 14).replace(";", "");
                } else {
                    schema = connection.getMetaData().getUserName();
                }
            } else if ("kingbase".equals(dbType)) {
                String url = connection.getMetaData().getURL();
                if (url.indexOf("searchpath") > 0) {
                    schema = url.substring(url.indexOf("searchpath") + 11);
                } else if (url.indexOf("currentSchema") > 0) {
                    schema = url.substring(url.indexOf("currentSchema") + 14);
                } else {
                    schema = "public";
                }
            } else if ("mysql".equals(dbType)) {
                String url = connection.getMetaData().getURL();
                int from = url.indexOf("://");
                int end = url.indexOf("?");
                String address = (end == -1) ? url.substring(from + 3) : url.substring(from + 3, end);
                int idx = address.lastIndexOf("/");
                schema = address.substring(idx + 1);
            } else if ("hive".equals(dbType)) {
                String url = connection.getMetaData().getURL();
                int from = url.indexOf("://");
                int end = url.indexOf("?");
                String address = (end == -1) ? url.substring(from + 3) : url.substring(from + 3, end);
                int idx = address.lastIndexOf("/");
                schema = address.substring(idx + 1);
            }
            if (!"oracle".equals(dbType)) {
                Map<String, String> map = getColumnNameAndTableNameByAlisaName(resultSetInformation, dbType, schema, tableName, columnName);
                columnName = map.get("columnName");
                tableName = map.get("tableName");
                schema = map.get("schema");
            }
            String mathKey = (ip + "_" + port + "_" + schema + "_" + tableName + "_" + columnName).toLowerCase().replace("`", "").replace("\"", "");
            RuleLoadUtil.writeLog("@@" + mathKey);
            if (EngineUtil.encryptionMap.isEmpty())
                EngineUtil.keyCacheFromFile();
            boolean ismaksing = EngineUtil.encryptionMap.containsKey(mathKey);
            if (ismaksing && (EncryptionGatewayManager.getParameterValue("projectid").length() == 0 || GatewayContext.isCurrentUserCanSeeDecInfo())) {
                Columninfo map = (Columninfo) EngineUtil.encryptionMap.get(mathKey);
                RuleLoadUtil.writeLog("@@" + value);
                value = EngineUtil.exeEngine(map, null, Boolean.valueOf(true), value, Boolean.valueOf(false));
                RuleLoadUtil.writeLog("@@" + value);
                EncryLogVO encryLogVO = new EncryLogVO();
                encryLogVO.setRalsql(resultSetInformation.getSql());
                encryLogVO.setStatus("");
                encryLogVO.setRalsql(null);
                encryLogVO.setExeSql(null);
                encryLogVO.setAccessSqlType(null);
                encryLogVO.setDecrypt(mathKey);
                encryLogVO.setEncryFieldSet(null);
                DblogClient.inputAuditLog(encryLogVO);
            }
            ismaksing = EngineUtil.maskingmap.containsKey(mathKey);
            if (ismaksing && GatewayContext.isCurrentUserNeedMask())
                try {
                    MaskingColumnInfo map = (MaskingColumnInfo) EngineUtil.maskingmap.get(mathKey);
                    if (null != map && null != map.getExpression() && !map.getExpression().trim().equals(""))
                        value = EngineUtil.exeMaskingEngine(map, value);
                } catch (Exception e1) {
                    e1.printStackTrace();
                    throw e1;
                } finally {
                }
        } catch (Exception e1) {
            e1.printStackTrace();
            throw new SQLException(e);
        } finally {
        }
        return value;
    }

    private Object getDecData(Object value, String sqlTemplate, Object column, String encPrefix) {
        StringBuilder stringBuilder = new StringBuilder();
        if (GatewayContext.isCurrentUserCanSeeDecInfo()) {
            String[] split = value.toString().split(EncryptionGatewayManager.getParameterValue("encryption.separator"));
            String likeFlag = EncryptionGatewayManager.getParameterValue("encryption.like.split");
            Set<Columninfo> secretKeySet = new HashSet<Columninfo>();
            for (String s : split) {
                if (s.contains(encPrefix)) {
                    Set<Columninfo> columninfos = sqlColumSecretKeyMap.get(sqlTemplate + "_" + column);
                    if (null != columninfos && columninfos.size() > 0) {
                        for (Columninfo columninfo : columninfos) {
                            if (s.startsWith(encPrefix)) {
                                if (s.contains(likeFlag) && "0".equals(columninfo.getIsLike()))
                                    continue;
                                try {
                                    s = (String) EngineUtil.exeEngine(columninfo, null, Boolean.valueOf(true), s, Boolean.valueOf(false));
                                } catch (Exception exception) {
                                }
                                if (!s.contains(encPrefix))
                                    break;
                                continue;
                            }
                            String substring = s.substring(0, s.indexOf(encPrefix));
                            if (s.contains(likeFlag) && "0".equals(columninfo.getIsLike()))
                                continue;
                            stringBuilder.append(substring);
                            s = s.substring(s.indexOf(encPrefix));
                            try {
                                s = (String) EngineUtil.exeEngine(columninfo, null, Boolean.valueOf(true), s, Boolean.valueOf(false));
                            } catch (Exception exception) {
                            }
                            if (!s.contains(encPrefix))
                                break;
                        }
                    } else {
                        for (Columninfo columninfo : EngineUtil.encryptionSet) {
                            if (s.startsWith(encPrefix)) {
                                if (s.contains(likeFlag) && "0".equals(columninfo.getIsLike()))
                                    continue;
                                try {
                                    s = (String) EngineUtil.exeEngine(columninfo, null, Boolean.valueOf(true), s, Boolean.valueOf(false));
                                } catch (Exception exception) {
                                }
                                if (!s.contains(encPrefix)) {
                                    secretKeySet.add(columninfo);
                                    sqlColumSecretKeyMap.put(sqlTemplate + "_" + column, secretKeySet);
                                    break;
                                }
                                continue;
                            }
                            String substring = s.substring(0, s.indexOf(encPrefix));
                            stringBuilder.append(substring);
                            s = s.substring(s.indexOf(encPrefix));
                            if (s.contains(likeFlag) && "0".equals(columninfo.getIsLike()))
                                continue;
                            try {
                                s = (String) EngineUtil.exeEngine(columninfo, null, Boolean.valueOf(true), s, Boolean.valueOf(false));
                            } catch (Exception exception) {
                            }
                            if (!s.contains(encPrefix)) {
                                secretKeySet.add(columninfo);
                                sqlColumSecretKeyMap.put(sqlTemplate + "_" + column, secretKeySet);
                                break;
                            }
                        }
                    }
                }
                stringBuilder.append(s);
            }
            value = stringBuilder.toString();
        }
        return value;
    }

    private String getDbType(Connection connection, String dbType) {
        try {
            String hiveurl = connection.toString();
            if (hiveurl.toLowerCase().contains("hive"))
                return "hive";
            String driverName = connection.getMetaData().getDriverName();
            if (driverName.toLowerCase().contains("mysql")) {
                dbType = "mysql";
            } else if (driverName.toLowerCase().contains("oracle")) {
                dbType = "oracle";
            } else if (driverName.toLowerCase().contains("postgresql")) {
                dbType = "postgresql";
                String url = connection.getMetaData().getURL();
                if (url.contains("gauss")) {
                    dbType = "gauss";
                    return dbType;
                }
                if (url.contains("greenplum")) {
                    dbType = "greenplum";
                    return dbType;
                }
            } else if (driverName.toLowerCase().contains("hive")) {
                dbType = "hive";
            } else if (driverName.toLowerCase().contains("dm")) {
                dbType = "dm";
            } else if (driverName.toLowerCase().contains("ibm")) {
                dbType = "db2";
            } else if (driverName.toLowerCase().contains("sql server")) {
                dbType = "sql server";
            } else if (driverName.toLowerCase().contains("kingbase")) {
                dbType = "kingbase";
            } else if (driverName.toLowerCase().contains("vastbase")) {
                dbType = "postgresql";
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return dbType;
    }

    public boolean getParsedMetaInfo(StatementInformation statementInformation, int columnIndex, Map<String, String> out) {
        List<Map<String, Object>> sqlParseList = statementInformation.sqlParse;
        Map<String, Object> sqlParse = sqlParseList.get(0);
        if (sqlParse == null || sqlParse.size() == 0)
            return false;
        List<Column> cols = (List<Column>) sqlParse.get("output-cols");
        if (cols == null || cols.size() == 0)
            return false;
        List<Column> idxCols = new ArrayList<Column>();
        for (Column col : cols) {
            if (col.seq == columnIndex) {
                String table = col.getTable();
                if (table == null || table.length() == 0)
                    continue;
                String fullname = col.getColumnName();
                if (fullname == null || fullname.length() == 0)
                    continue;
                int idx = fullname.toLowerCase().indexOf(table.toLowerCase());
                if (idx == -1)
                    continue;
                String cname = fullname.substring(idx + table.length() + 1);
                out.put("columnName", cname);
                out.put("tableName", table);
                return true;
            }
        }
        return false;
    }

    public String getFieldTableName(String sql, String field, String dbType) {
        try {
            String tableName = "";
            List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);
            SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(DbType.of(dbType));
            SQLStatement sqlStatement = stmtList.get(0);
            sqlStatement.accept((SQLASTVisitor) visitor);
            Collection<TableStat.Column> columns = visitor.getColumns();
            for (TableStat.Column column : columns) {
                if (column.getName().equalsIgnoreCase(field)) {
                    tableName = column.getTable();
                    break;
                }
            }
            if ((tableName == null || tableName.length() == 0) && columns.size() > 0)
                tableName = ((TableStat.Column) columns.iterator().next()).getTable();
            if (tableName.contains("."))
                tableName = tableName.split("\\.")[1];
            return tableName;
        } catch (Exception e) {
            return null;
        }
    }

    public Object onAfterResultSetGet(ResultSetInformation resultSetInformation, int columnIndex, Object value, SQLException e) throws Exception {
        if (!GatewayContext.isPluginEnabled())
            return value;
        if (value == null || (value instanceof String && StringUtils.isBlank((String) value)))
            return value;
        String encPrefix = EncryptionGatewayManager.getParameterValue("encryption.label");
        if (value.toString().contains(encPrefix) && GatewayContext.isCurrentUserCanSeeDecInfo()) {
            String sqlTemplate = getSqlTemplate(resultSetInformation);
            RuleLoadUtil.writeLog("@@" + value);
            value = getDecData(value, sqlTemplate, Integer.valueOf(columnIndex), encPrefix);
            RuleLoadUtil.writeLog("@@" + value);
        }
        if (!EncryptionGatewayManager.checkParameterFlag("maskingRule"))
            return value;
        ResultSetMetaData metaData = resultSetInformation.getResultSet().getMetaData();
        String schema = resultSetInformation.getResultSet().getMetaData().getCatalogName(columnIndex);
        String tableName = metaData.getTableName(columnIndex);
        String columnName = metaData.getColumnLabel(columnIndex);
        String columnType = metaData.getColumnTypeName(columnIndex);
        if (columnName == null || "".equals(columnName))
            columnName = metaData.getColumnName(columnIndex);
        Connection connection = resultSetInformation.getConnectionInformation().getConnection();
        String urlTemp = connection.getMetaData().getURL();
        Map<String, String> ipAndPortMap = getIpAndPort(urlTemp);
        String ip = ipAndPortMap.get("ip");
        String port = ipAndPortMap.get("port");
        String driverName = resultSetInformation.getConnectionInformation().getConnection().getMetaData().getDriverName();
        String urlDbType = resultSetInformation.getConnectionInformation().getUrl();
        String dbType = "";
        dbType = ConnectionWrapper.getDbType(driverName, urlDbType, dbType);
        if ("oracle".equals(dbType)) {
            int i;
            schema = connection.getMetaData().getUserName();
            StatementInformation statementInformation = resultSetInformation.getStatementInformation();
            String sqlAll = statementInformation.getSql();
            if (sqlAll.indexOf("-- appUsername=") > 0)
                sqlAll = sqlAll.substring(0, sqlAll.indexOf("-- appUsername=")).trim();
            if (sqlAll.endsWith(";"))
                sqlAll = sqlAll.substring(0, sqlAll.length() - 1);
            String[] splitSql = sqlAll.split(";");
            if (splitSql.length == 1) {
                i = 0;
            } else {
                for (i = 0; i < splitSql.length; i++) {
                    String trim = splitSql[i].toLowerCase().trim();
                    if (trim.startsWith("select"))
                        break;
                    if (trim.contains("*/")) {
                        int index = trim.indexOf("*/");
                        trim = trim.substring(index + 2).trim();
                        if (trim.startsWith("select"))
                            break;
                    }
                }
                if (i == splitSql.length)
                    i = splitSql.length - 1;
            }
            List<Map<String, Object>> sqlParseList = (List<Map<String, Object>>) ConnectionWrapper.sqlParseMap.get(sqlAll);
            if (sqlParseList == null || sqlParseList.isEmpty())
                sqlParseList = statementInformation.sqlParse;
            if (sqlParseList == null || sqlParseList.isEmpty())
                return value;
            Map<String, Object> sqlParse = sqlParseList.get(i);
            if (sqlParse != null && !sqlParse.isEmpty()) {
                List<Column> cols = (List<Column>) sqlParse.get("output-cols");
                if (cols != null && cols.size() > 0)
                    for (Column col : cols) {
                        if (col.seq == columnIndex) {
                            String table = col.getTable();
                            if (table == null || table.length() == 0)
                                continue;
                            String fullname = col.getColumnName();
                            if (fullname == null || fullname.length() == 0)
                                continue;
                            int idx = fullname.toLowerCase().indexOf(table.toLowerCase());
                            if (idx == -1)
                                continue;
                            String cname = fullname.substring(idx + table.length() + 1);
                            columnName = cname;
                            tableName = table;
                            schema = col.getSchema();
                        }
                    }
            }
            if (columnType.toLowerCase(Locale.ROOT).contains("char") &&
                    value != null && value instanceof String && !"".equals(value.toString()))
                value = value.toString().trim();
        } else if ("postgresql".equals(dbType) || "greenplum".equals(dbType) || "gauss".equals(dbType)) {
            String url = connection.getMetaData().getURL();
            if (url.indexOf("searchpath") > 0) {
                schema = url.substring(url.indexOf("searchpath") + 11);
            } else if (url.indexOf("currentSchema") > 0) {
                schema = url.substring(url.indexOf("currentSchema") + 14);
            } else {
                schema = "public";
            }
        } else if ("sql server".equals(dbType)) {
            String url = connection.getMetaData().getURL();
            if (url.indexOf("applicationName") > 0) {
                schema = url.substring(url.indexOf("applicationName") + "applicationName".length() + 1);
                if (schema.indexOf(";") != -1)
                    schema = schema.substring(0, schema.indexOf(";"));
            } else {
                schema = "dbo";
            }
        } else if ("dm".equals(dbType)) {
            String url = resultSetInformation.getConnectionInformation().getUrl();
            if (url.toLowerCase().contains("schema=")) {
                schema = url.substring(url.toLowerCase().indexOf("schema=") + 7);
            } else {
                int from = url.indexOf("://");
                int end = url.indexOf("?");
                String address = (end == -1) ? url.substring(from + 3) : url.substring(from + 3, end);
                int idx = address.lastIndexOf("/");
                schema = address.substring(idx + 1);
            }
        } else if ("db2".equals(dbType)) {
            String url = resultSetInformation.getConnectionInformation().getUrl();
            if (url.contains("currentSchema=")) {
                schema = url.substring(url.indexOf("currentSchema=") + 14).replace(";", "");
            } else {
                schema = connection.getMetaData().getUserName();
            }
        } else if ("kingbase".equals(dbType)) {
            String url = connection.getMetaData().getURL();
            if (url.indexOf("searchpath") > 0) {
                schema = url.substring(url.indexOf("searchpath") + 11);
            } else if (url.indexOf("currentSchema") > 0) {
                schema = url.substring(url.indexOf("currentSchema") + 14);
            } else {
                schema = "public";
            }
        } else if ("mysql".equals(dbType)) {
            String url = connection.getMetaData().getURL();
            int from = url.indexOf("://");
            int end = url.indexOf("?");
            String address = (end == -1) ? url.substring(from + 3) : url.substring(from + 3, end);
            int idx = address.lastIndexOf("/");
            schema = address.substring(idx + 1);
        } else if ("mariadb".equals(dbType)) {
            String url = connection.getMetaData().getURL();
            int from = url.indexOf("://");
            int end = url.indexOf("?");
            String address = (end == -1) ? url.substring(from + 3) : url.substring(from + 3, end);
            int idx = address.lastIndexOf("/");
            schema = address.substring(idx + 1);
        } else if ("hive".equals(dbType)) {
            String url = connection.getMetaData().getURL();
            int from = url.indexOf("://");
            int end = url.indexOf("?");
            String address = (end == -1) ? url.substring(from + 3) : url.substring(from + 3, end);
            int idx = address.lastIndexOf("/");
            schema = address.substring(idx + 1);
        }
        if (value == null)
            return value;
        if (!"oracle".equals(dbType)) {
            Map<String, String> map = getColumnNameAndTableNameByAlisaName(resultSetInformation, dbType, schema, tableName, columnName);
            columnName = map.get("columnName");
            tableName = map.get("tableName");
            schema = map.get("schema");
        }
        String mathKey = (ip + "_" + port + "_" + schema + "_" + tableName + "_" + columnName).toLowerCase().replace("`", "").replace("\"", "");
        RuleLoadUtil.writeLog("@@" + mathKey);
        if (EngineUtil.encryptionMap.isEmpty())
            EngineUtil.keyCacheFromFile();
        boolean isEncrpt = EngineUtil.encryptionMap.containsKey(mathKey);
        if (isEncrpt && (EncryptionGatewayManager.getParameterValue("projectid").length() == 0 || GatewayContext.isCurrentUserCanSeeDecInfo()))
            try {
                Columninfo map = (Columninfo) EngineUtil.encryptionMap.get(mathKey);
                RuleLoadUtil.writeLog("@@" + value);
                value = EngineUtil.exeEngine(map, null, Boolean.valueOf(true), value, Boolean.valueOf(false));
                RuleLoadUtil.writeLog("@@" + value);
            } catch (Exception e1) {
                e1.printStackTrace();
                throw new SQLException(e1);
            } finally {
            }
        boolean ismaksing = EngineUtil.maskingmap.containsKey(mathKey);
        if (ismaksing && GatewayContext.isCurrentUserNeedMask())
            try {
                MaskingColumnInfo map = (MaskingColumnInfo) EngineUtil.maskingmap.get(mathKey);
                if (null != map && null != map.getExpression() && !map.getExpression().trim().equals(""))
                    value = EngineUtil.exeMaskingEngine(map, value);
            } catch (Exception e1) {
                e1.printStackTrace();
                throw e1;
            } finally {
            }
        return value;
    }

    private Map<String, String> getColumnNameAndTableNameByAlisaName(ResultSetInformation resultSetInformation, String dbType, String schema, String tableName, String columnName) {
        int i;
        Map<String, String> map = new HashMap<String, String>();
        StatementInformation statementInformation = resultSetInformation.getStatementInformation();
        String sqlTemp = statementInformation.getSql();
        if (sqlTemp.indexOf("-- appUsername=") > 0)
            sqlTemp = sqlTemp.substring(0, sqlTemp.indexOf("-- appUsername=")).trim();
        List<Map<String, Object>> sqlParseList = (List<Map<String, Object>>) ConnectionWrapper.sqlParseMap.get(sqlTemp);
        if (sqlParseList == null || sqlParseList.isEmpty())
            sqlParseList = statementInformation.sqlParse;
        if (sqlParseList == null || sqlParseList.isEmpty()) {
            try {
                ConnectionInformation connectionInformation = resultSetInformation.getConnectionInformation();
                String str1 = resultSetInformation.getStatementInformation().getStatementQuery();
                Map<String, String> params = new HashMap<String, String>();
                params.put("sql", sqlTemp);
                params.put("dbType", dbType);
                params.put("schema", schema);
                params.put("encryption", "1");
                String url = statementInformation.getConnectionInformation().getConnection().getMetaData().getURL();
                params.put("url", url);
                SqlUtil sqlUtil = new SqlUtil();
                List<Map<String, Object>> stringObjectMapList = sqlUtil.parseSqlStructureEnc(params);
                statementInformation.sqlParse = stringObjectMapList;
                ConnectionWrapper.sqlParseMap.put(sqlTemp, stringObjectMapList);
                sqlParseList = stringObjectMapList;
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (sqlParseList == null || sqlParseList.isEmpty())
                return new HashMap<String, String>();
        }
        String sql = statementInformation.getStatementQuery().toLowerCase();
        String sqlAll = statementInformation.getSql().trim();
        if (sqlAll.endsWith(";"))
            sqlAll = sqlAll.substring(0, sqlAll.length() - 1);
        String[] splitSql = sqlAll.split(";");
        if (splitSql.length == 1) {
            i = 0;
        } else {
            for (i = 0; i < splitSql.length; i++) {
                String trim = splitSql[i].toLowerCase().trim();
                if (trim.startsWith("select"))
                    break;
                if (trim.contains("*/")) {
                    int index = trim.indexOf("*/");
                    trim = trim.substring(index + 2).trim();
                    if (trim.startsWith("select"))
                        break;
                }
            }
            if (i == splitSql.length)
                i = splitSql.length - 1;
        }
        Map<String, Object> sqlParse = sqlParseList.get(i);
        List<Column> list = (List<Column>) sqlParse.get("columnList");
        if (list != null && list.size() > 0)
            for (Column column : list) {
                if (columnName.equalsIgnoreCase(column.getColumnAlisa())) {
                    String[] split = column.getColumnName().split("\\.");
                    if (split.length == 2) {
                        map.put("columnName", column.getColumnName().split("\\.")[1].replace("\"", ""));
                    } else {
                        map.put("columnName", column.getColumnName().replace("\"", ""));
                    }
                    map.put("tableName", column.getTable());
                    map.put("schema", column.getSchema());
                    return map;
                }
            }
        map.put("columnName", columnName);
        map.put("tableName", tableName);
        map.put("schema", schema);
        String columnNameTmp = "";
        if (list != null && list.size() > 0)
            for (Column column : list) {
                String[] split = column.getColumnName().split("\\.");
                if (split.length == 2) {
                    columnNameTmp = column.getColumnName().split("\\.")[1].replace("\"", "");
                } else {
                    columnNameTmp = column.getColumnName().replace("\"", "");
                }
                if (columnNameTmp.equalsIgnoreCase(columnName)) {
                    map.put("tableName", column.getTable());
                    map.put("schema", column.getSchema());
                }
            }
        return map;
    }

    public Object encData(Object value, String tableName, String columnName, String schema) throws Exception {
        for (JsonRootBean authBean : EngineUtil.encryptonBeanList) {
            String maskingColumnname = "";
            String desensitizationexpression = "Sm4Util:true";
            List<TableInfo> tableinfoList = authBean.getTableInfo();
            for (int i = 0; i < tableinfoList.size(); i++) {
                List<Columninfo> fieldinfoList = ((TableInfo) tableinfoList.get(i)).getColumninfo();
                String maskingTableName = ((TableInfo) tableinfoList.get(i)).getTablename();
                String maskingSchemaName = authBean.getSchema();
                for (int j = 0; j < fieldinfoList.size(); j++) {
                    Boolean flag = Boolean.valueOf(false);
                    Columninfo fieldinfo = fieldinfoList.get(j);
                    maskingColumnname = fieldinfo.getColumnname();
                    if (StringUtils.isNotBlank(maskingColumnname) && tableName.equalsIgnoreCase(maskingTableName) && columnName.equalsIgnoreCase(maskingColumnname) && maskingSchemaName.equalsIgnoreCase(schema)) {
                        value = EngineUtil.exeEngine(fieldinfo, null, flag, value, Boolean.valueOf(true));
                        break;
                    }
                }
            }
        }
        return value;
    }

    private Object getObject(Object value, String tableName, String columnLabel, String schema, ConnectionInfo connectionInfo) throws Exception {
        Object obj = EngineUtil.dataEngine(tableName, columnLabel, value, schema, connectionInfo);
        return obj;
    }

    public static Map<String, String> getIpAndPort(String url) {
        Map<String, String> ipMap = ipPortMap.get(url);
        if (ipMap != null && ipMap.size() > 0)
            return ipMap;
        Map<String, String> map = new HashMap<String, String>(2);
        // 修改后的代码 - 支持IP、localhost和域名
        Pattern p = Pattern.compile("//([^:/\\s]+):(\\d+)");
        Matcher m = p.matcher(url);
        while (m.find()) {
            map.put("ip", m.group(1));
            map.put("port", m.group(2));
        }
        if (null != EncryptionGatewayManager.getParameterValue("dataBase.ip") && !"".equals(EncryptionGatewayManager.getParameterValue("dataBase.ip"))) {
            map.put("ip", EncryptionGatewayManager.getParameterValue("dataBase.ip"));
            map.put("port", EncryptionGatewayManager.getParameterValue("dataBase.port"));
        }
        ipPortMap.put(url, map);
        return map;
    }

    public String getSqlTemplate(ResultSetInformation resultSetInformation) {
        if (null == resultSetInformation.getSqlTemplate() || "".equals(resultSetInformation.getSql()))
            resultSetInformation.setSqlTemplate(resultSetInformation.getSql());
        return resultSetInformation.getSqlTemplate();
    }

    public static void main(String[] args) {
        String url = "jdbc:dm://192.168.2.228:5236/aa?currentSchema=encryption";
    }
}