BaseJdbcLogger.java

  1. /*
  2.  *    Copyright 2009-2021 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.  *       http://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 org.apache.ibatis.logging.jdbc;

  17. import java.lang.reflect.Method;
  18. import java.sql.Array;
  19. import java.sql.PreparedStatement;
  20. import java.sql.SQLException;
  21. import java.util.ArrayList;
  22. import java.util.Arrays;
  23. import java.util.HashMap;
  24. import java.util.HashSet;
  25. import java.util.List;
  26. import java.util.Map;
  27. import java.util.Set;
  28. import java.util.stream.Collectors;

  29. import org.apache.ibatis.builder.SqlSourceBuilder;
  30. import org.apache.ibatis.logging.Log;
  31. import org.apache.ibatis.reflection.ArrayUtil;

  32. /**
  33.  * Base class for proxies to do logging.
  34.  *
  35.  * @author Clinton Begin
  36.  * @author Eduardo Macarron
  37.  */
  38. public abstract class BaseJdbcLogger {

  39.   protected static final Set<String> SET_METHODS;
  40.   protected static final Set<String> EXECUTE_METHODS = new HashSet<>();

  41.   private final Map<Object, Object> columnMap = new HashMap<>();

  42.   private final List<Object> columnNames = new ArrayList<>();
  43.   private final List<Object> columnValues = new ArrayList<>();

  44.   protected final Log statementLog;
  45.   protected final int queryStack;

  46.   /*
  47.    * Default constructor
  48.    */
  49.   public BaseJdbcLogger(Log log, int queryStack) {
  50.     this.statementLog = log;
  51.     if (queryStack == 0) {
  52.       this.queryStack = 1;
  53.     } else {
  54.       this.queryStack = queryStack;
  55.     }
  56.   }

  57.   static {
  58.     SET_METHODS = Arrays.stream(PreparedStatement.class.getDeclaredMethods())
  59.             .filter(method -> method.getName().startsWith("set"))
  60.             .filter(method -> method.getParameterCount() > 1)
  61.             .map(Method::getName)
  62.             .collect(Collectors.toSet());

  63.     EXECUTE_METHODS.add("execute");
  64.     EXECUTE_METHODS.add("executeUpdate");
  65.     EXECUTE_METHODS.add("executeQuery");
  66.     EXECUTE_METHODS.add("addBatch");
  67.   }

  68.   protected void setColumn(Object key, Object value) {
  69.     columnMap.put(key, value);
  70.     columnNames.add(key);
  71.     columnValues.add(value);
  72.   }

  73.   protected Object getColumn(Object key) {
  74.     return columnMap.get(key);
  75.   }

  76.   protected String getParameterValueString() {
  77.     List<Object> typeList = new ArrayList<>(columnValues.size());
  78.     for (Object value : columnValues) {
  79.       if (value == null) {
  80.         typeList.add("null");
  81.       } else {
  82.         typeList.add(objectValueString(value) + "(" + value.getClass().getSimpleName() + ")");
  83.       }
  84.     }
  85.     final String parameters = typeList.toString();
  86.     return parameters.substring(1, parameters.length() - 1);
  87.   }

  88.   protected String objectValueString(Object value) {
  89.     if (value instanceof Array) {
  90.       try {
  91.         return ArrayUtil.toString(((Array) value).getArray());
  92.       } catch (SQLException e) {
  93.         return value.toString();
  94.       }
  95.     }
  96.     return value.toString();
  97.   }

  98.   protected String getColumnString() {
  99.     return columnNames.toString();
  100.   }

  101.   protected void clearColumnInfo() {
  102.     columnMap.clear();
  103.     columnNames.clear();
  104.     columnValues.clear();
  105.   }

  106.   protected String removeExtraWhitespace(String original) {
  107.     return SqlSourceBuilder.removeExtraWhitespaces(original);
  108.   }

  109.   protected boolean isDebugEnabled() {
  110.     return statementLog.isDebugEnabled();
  111.   }

  112.   protected boolean isTraceEnabled() {
  113.     return statementLog.isTraceEnabled();
  114.   }

  115.   protected void debug(String text, boolean input) {
  116.     if (statementLog.isDebugEnabled()) {
  117.       statementLog.debug(prefix(input) + text);
  118.     }
  119.   }

  120.   protected void trace(String text, boolean input) {
  121.     if (statementLog.isTraceEnabled()) {
  122.       statementLog.trace(prefix(input) + text);
  123.     }
  124.   }

  125.   private String prefix(boolean isInput) {
  126.     char[] buffer = new char[queryStack * 2 + 2];
  127.     Arrays.fill(buffer, '=');
  128.     buffer[queryStack * 2 + 1] = ' ';
  129.     if (isInput) {
  130.       buffer[queryStack * 2] = '>';
  131.     } else {
  132.       buffer[0] = '<';
  133.     }
  134.     return new String(buffer);
  135.   }

  136. }