blob: affb888bd430f868b060f6513a527cca64b9aeb7 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.ode.utils;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.Statement;
import java.util.*;
import javax.sql.DataSource;
import org.slf4j.Logger;
public class LoggingInterceptor<T> implements InvocationHandler {
private static final Set<String> PARAMSTYPES = new HashSet<String>();
static {
PARAMSTYPES.add("setArray");
PARAMSTYPES.add("setBigDecimal");
PARAMSTYPES.add("setBoolean");
PARAMSTYPES.add("setByte");
PARAMSTYPES.add("setBytes");
PARAMSTYPES.add("setDate");
PARAMSTYPES.add("setDouble");
PARAMSTYPES.add("setFloat");
PARAMSTYPES.add("setInt");
PARAMSTYPES.add("setLong");
PARAMSTYPES.add("setObject");
PARAMSTYPES.add("setRef");
PARAMSTYPES.add("setShort");
PARAMSTYPES.add("setString");
PARAMSTYPES.add("setTime");
PARAMSTYPES.add("setTimestamp");
PARAMSTYPES.add("setURL");
}
private Logger _log;
private T _delegate;
private Map<String, Object> _paramsByName = new TreeMap<String, Object>();
private Map<Integer, Object> _paramsByIdx = new TreeMap<Integer, Object>();
public LoggingInterceptor(T delegate, Logger log) {
_log = log;
_delegate = delegate;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
try {
if (method.getDeclaringClass() == DataSource.class
&& "getConnection".equals(method.getName())) {
Connection conn = (Connection)method.invoke(_delegate, args);
print("getConnection (tx=" + conn.getTransactionIsolation() + ")");
return Proxy.newProxyInstance(_delegate.getClass().getClassLoader(),
new Class[] {Connection.class}, new LoggingInterceptor<Connection>(conn, _log));
} else if (method.getDeclaringClass() == Connection.class
&& Statement.class.isAssignableFrom(method.getReturnType())) {
Statement stmt = (Statement)method.invoke(_delegate, args);
print(method, args);
return Proxy.newProxyInstance(_delegate.getClass().getClassLoader(),
new Class[] {method.getReturnType()}, new LoggingInterceptor<Statement>(stmt, _log));
} else {
print(method, args);
return method.invoke(_delegate, args);
}
} catch (InvocationTargetException e) {
throw e.getTargetException();
}
}
private void print(Method method, Object[] args) {
if (shouldPrint()) {
// JDBC Connection
if ("prepareStatement".equals(method.getName())) {
print("prepareStatement: " + args[0]);
} else if ("prepareCall".equals(method.getName())) {
print("prepareCall: " + args[0]);
} else if ("close".equals(method.getName())) {
print("close()");
} else if ("commit".equals(method.getName())) {
print("commit()");
} else if ("rollback".equals(method.getName())) {
print("rollback()");
} else if ("setTransactionIsolation".equals(method.getName())) {
print("Set isolation level to " + args[0]);
}
// JDBC Statement
else if (method.getName().startsWith("execute") && args != null && args.length == 1 && args[0] instanceof String) {
print(method.getName() + "(" + args[0] + "), " + getParams());
} else if (method.getName().startsWith("execute")) {
print(method.getName() + ", " + getParams());
} else if ("clearParameters".equals(method.getName())) {
_paramsByIdx.clear();
_paramsByName.clear();
} else if ("setNull".equals(method.getName())) {
if (String.class.isAssignableFrom(args[0].getClass())) {
_paramsByName.put((String)args[0], null);
} else if (Integer.class.isAssignableFrom(args[0].getClass())) {
_paramsByIdx.put((Integer)args[0], null);
}
} else if (PARAMSTYPES.contains(method.getName())){
if (String.class.isAssignableFrom(args[0].getClass())) {
_paramsByName.put((String)args[0], args[1]);
} else if (Integer.class.isAssignableFrom(args[0].getClass())) {
_paramsByIdx.put((Integer)args[0], args[1]);
}
}
}
}
private String getParams() {
if (_paramsByIdx.size() > 0 || _paramsByName.size() > 0) {
StringBuffer buf = new StringBuffer();
buf.append("bound ");
for (Map.Entry<Integer, Object> entry : _paramsByIdx.entrySet()) {
try {
buf.append("(").append(entry.getKey()).append(",").append(entry.getValue()).append(") ");
} catch (Throwable e) {
// We don't want to mess with the connection just for logging
return "[e]";
}
}
for (Map.Entry<String, Object> entry : _paramsByName.entrySet()) {
try {
buf.append("(").append(entry.getKey()).append(",").append(entry.getValue()).append(") ");
} catch (Throwable e) {
// We don't want to mess with the connection just for logging
return "[e]";
}
}
return buf.toString();
}
return "w/o params";
}
private boolean shouldPrint() {
if (_log != null)
return _log.isDebugEnabled();
else return true;
}
private void print(String str) {
if (_log != null)
_log.debug(str);
else System.out.println(str);
}
public static DataSource createLoggingDS(DataSource ds, Logger log) {
return (DataSource)Proxy.newProxyInstance(ds.getClass().getClassLoader(),
new Class[] {DataSource.class}, new LoggingInterceptor<DataSource>(ds,log));
}
}