View Javadoc
1   /*
2    * Copyright 2004-2022 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *    https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package com.ibatis.common.jdbc.logging;
17  
18  import com.ibatis.common.beans.ClassInfo;
19  import com.ibatis.common.logging.Log;
20  import com.ibatis.common.logging.LogFactory;
21  
22  import java.lang.reflect.InvocationHandler;
23  import java.lang.reflect.Method;
24  import java.lang.reflect.Proxy;
25  import java.sql.CallableStatement;
26  import java.sql.PreparedStatement;
27  import java.sql.ResultSet;
28  
29  /**
30   * PreparedStatement proxy to add logging.
31   */
32  public class PreparedStatementLogProxy extends BaseLogProxy implements InvocationHandler {
33  
34    /** The Constant log. */
35    private static final Log log = LogFactory.getLog(PreparedStatement.class);
36  
37    /** The statement. */
38    private PreparedStatement statement;
39  
40    /** The sql. */
41    private String sql;
42  
43    /**
44     * Instantiates a new prepared statement log proxy.
45     *
46     * @param stmt
47     *          the stmt
48     * @param sql
49     *          the sql
50     */
51    private PreparedStatementLogProxy(PreparedStatement stmt, String sql) {
52      this.statement = stmt;
53      this.sql = sql;
54    }
55  
56    public Object invoke(Object proxy, Method method, Object[] params) throws Throwable {
57      try {
58        if (EXECUTE_METHODS.contains(method.getName())) {
59          if (log.isDebugEnabled()) {
60            log.debug("{pstm-" + id + "} Executing Statement: " + removeBreakingWhitespace(sql));
61            log.debug("{pstm-" + id + "} Parameters: " + getValueString());
62            log.debug("{pstm-" + id + "} Types: " + getTypeString());
63          }
64          clearColumnInfo();
65          if ("executeQuery".equals(method.getName())) {
66            ResultSet rs = (ResultSet) method.invoke(statement, params);
67            if (rs != null) {
68              return ResultSetLogProxy.newInstance(rs);
69            } else {
70              return null;
71            }
72          } else {
73            return method.invoke(statement, params);
74          }
75        } else if (SET_METHODS.contains(method.getName())) {
76          if ("setNull".equals(method.getName())) {
77            setColumn(params[0], null);
78          } else {
79            setColumn(params[0], params[1]);
80          }
81          return method.invoke(statement, params);
82        } else if ("getResultSet".equals(method.getName())) {
83          ResultSet rs = (ResultSet) method.invoke(statement, params);
84          if (rs != null) {
85            return ResultSetLogProxy.newInstance(rs);
86          } else {
87            return null;
88          }
89        } else if ("equals".equals(method.getName())) {
90          Object ps = params[0];
91          if (ps instanceof Proxy) {
92            return new Boolean(proxy == ps);
93          }
94          return new Boolean(false);
95        } else if ("hashCode".equals(method.getName())) {
96          return Integer.valueOf(proxy.hashCode());
97        } else {
98          return method.invoke(statement, params);
99        }
100     } catch (Throwable t) {
101       throw ClassInfo.unwrapThrowable(t);
102     }
103   }
104 
105   /**
106    * Creates a logging version of a PreparedStatement.
107    *
108    * @param stmt
109    *          - the statement
110    * @param sql
111    *          - the sql statement
112    *
113    * @return - the proxy
114    */
115   public static PreparedStatement newInstance(PreparedStatement stmt, String sql) {
116     InvocationHandler handler = new PreparedStatementLogProxy(stmt, sql);
117     ClassLoader cl = PreparedStatement.class.getClassLoader();
118     return (PreparedStatement) Proxy.newProxyInstance(cl,
119         new Class[] { PreparedStatement.class, CallableStatement.class }, handler);
120   }
121 
122   /**
123    * Return the wrapped prepared statement.
124    *
125    * @return the PreparedStatement
126    */
127   public PreparedStatement getPreparedStatement() {
128     return statement;
129   }
130 
131 }