001/**
002 * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
003 * <p>
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 * <p>
008 * http://www.apache.org/licenses/LICENSE-2.0
009 * <p>
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package com.mybatisflex.core.audit;
017
018import com.mybatisflex.core.mybatis.TypeHandlerObject;
019import com.mybatisflex.core.util.DateUtil;
020
021import java.io.Serializable;
022import java.lang.reflect.Array;
023import java.lang.reflect.Proxy;
024import java.sql.PreparedStatement;
025import java.sql.SQLException;
026import java.time.LocalDateTime;
027import java.util.ArrayList;
028import java.util.Date;
029import java.util.HashMap;
030import java.util.List;
031import java.util.Map;
032import java.util.regex.Matcher;
033
034public class AuditMessage implements Serializable {
035
036    private String platform;
037    private String module;
038    private String url;
039    private String bizId; //自定义业务ID
040
041    private String user;
042    private String userIp;
043    private String hostIp;
044
045    private String query;
046    private List<Object> queryParams;
047    private int queryCount;
048
049    private long queryTime;     // Sql 执行的当前时间,单位毫秒
050    private long elapsedTime;   // Sql 执行消耗的时间,单位毫秒
051
052    private Map<String, Object> metas; //其他信息,元信息
053
054
055    public String getPlatform() {
056        return platform;
057    }
058
059    public void setPlatform(String platform) {
060        this.platform = platform;
061    }
062
063    public String getModule() {
064        return module;
065    }
066
067    public void setModule(String module) {
068        this.module = module;
069    }
070
071    public String getUrl() {
072        return url;
073    }
074
075    public void setUrl(String url) {
076        this.url = url;
077    }
078
079    public String getBizId() {
080        return bizId;
081    }
082
083    public void setBizId(String bizId) {
084        this.bizId = bizId;
085    }
086
087    public String getUser() {
088        return user;
089    }
090
091    public void setUser(String user) {
092        this.user = user;
093    }
094
095    public String getUserIp() {
096        return userIp;
097    }
098
099    public void setUserIp(String userIp) {
100        this.userIp = userIp;
101    }
102
103    public String getHostIp() {
104        return hostIp;
105    }
106
107    public void setHostIp(String hostIp) {
108        this.hostIp = hostIp;
109    }
110
111    public String getQuery() {
112        return query;
113    }
114
115    public void setQuery(String query) {
116        this.query = query;
117    }
118
119    public List<Object> getQueryParams() {
120        return queryParams;
121    }
122
123    public void setQueryParams(List<Object> queryParams) {
124        this.queryParams = queryParams;
125    }
126
127    public void addParams(Object... objects) {
128        if (queryParams == null) {
129            queryParams = new ArrayList<>();
130        }
131        for (Object object : objects) {
132            if (object != null && (object.getClass().isArray()
133                    || object.getClass() == int[].class
134                    || object.getClass() == long[].class
135                    || object.getClass() == short[].class
136                    || object.getClass() == float[].class
137                    || object.getClass() == double[].class)
138            ) {
139                for (int i = 0; i < Array.getLength(object); i++) {
140                    addParams(Array.get(object, i));
141                }
142            } else if (object instanceof TypeHandlerObject) {
143                try {
144                    ((TypeHandlerObject) object).setParameter(createPreparedStatement(), 0);
145                } catch (SQLException e) {
146                    //ignore
147                }
148            } else {
149                queryParams.add(object);
150            }
151        }
152    }
153
154    public String getFullSql() {
155        String sql = getQuery();
156        List<Object> params = getQueryParams();
157        if (params != null) {
158            for (Object value : params) {
159                // null
160                if (value == null) {
161                    sql = sql.replaceFirst("\\?", "null");
162                }
163                // number
164                else if (value instanceof Number || value instanceof Boolean) {
165                    sql = sql.replaceFirst("\\?", value.toString());
166                }
167                // other
168                else {
169                    StringBuilder sb = new StringBuilder();
170                    sb.append("'");
171                    if (value instanceof Date) {
172                        sb.append(DateUtil.toDateTimeString((Date) value));
173                    } else if (value instanceof LocalDateTime) {
174                        sb.append(DateUtil.toDateTimeString(DateUtil.toDate((LocalDateTime) value)));
175                    } else {
176                        sb.append(value);
177                    }
178                    sb.append("'");
179                    sql = sql.replaceFirst("\\?", Matcher.quoteReplacement(sb.toString()));
180                }
181            }
182        }
183        return sql;
184    }
185
186    private PreparedStatement createPreparedStatement() {
187        return (PreparedStatement) Proxy.newProxyInstance(
188                AuditMessage.class.getClassLoader(),
189                new Class[]{PreparedStatement.class}, (proxy, method, args) -> {
190                    if (args != null && args.length == 2){
191                        addParams(args[1]);
192                    }
193                    return null;
194                });
195    }
196
197    public int getQueryCount() {
198        return queryCount;
199    }
200
201    public void setQueryCount(int queryCount) {
202        this.queryCount = queryCount;
203    }
204
205    public long getQueryTime() {
206        return queryTime;
207    }
208
209    public void setQueryTime(long queryTime) {
210        this.queryTime = queryTime;
211    }
212
213    public long getElapsedTime() {
214        return elapsedTime;
215    }
216
217    public void setElapsedTime(long elapsedTime) {
218        this.elapsedTime = elapsedTime;
219    }
220
221    public Map<String, Object> getMetas() {
222        return metas;
223    }
224
225    public void setMetas(Map<String, Object> metas) {
226        this.metas = metas;
227    }
228
229    public void addMeta(String key, Object value) {
230        if (metas == null) {
231            metas = new HashMap<>();
232        }
233        metas.put(key, value);
234    }
235
236    @Override
237    public String toString() {
238        return "AuditMessage{" +
239                "platform='" + platform + '\'' +
240                ", module='" + module + '\'' +
241                ", url='" + url + '\'' +
242                ", bizId='" + bizId + '\'' +
243                ", user='" + user + '\'' +
244                ", userIp='" + userIp + '\'' +
245                ", hostIp='" + hostIp + '\'' +
246                ", query='" + query + '\'' +
247                ", queryParams=" + queryParams +
248                ", queryCount=" + queryCount +
249                ", queryTime=" + queryTime +
250                ", elapsedTime=" + elapsedTime +
251                ", metas=" + metas +
252                '}';
253    }
254}