blob: eac84838d46b4f07db1748f5b9274b6b341fda34 [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.tomcat.jdbc.pool;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.jdbc.pool.interceptor.AbstractCreateStatementInterceptor;
public class StatementFacade extends AbstractCreateStatementInterceptor {
private static final Log logger = LogFactory.getLog(StatementFacade.class);
protected StatementFacade(JdbcInterceptor interceptor) {
setUseEquals(interceptor.isUseEquals());
setNext(interceptor);
}
@Override
public void closeInvoked() {
// nothing to do
}
/**
* Creates a statement interceptor to monitor query response times
*/
@Override
public Object createStatement(Object proxy, Method method, Object[] args, Object statement, long time) {
try {
String name = method.getName();
Constructor<?> constructor = null;
String sql = null;
if (compare(CREATE_STATEMENT, name)) {
// createStatement
constructor = getConstructor(CREATE_STATEMENT_IDX, Statement.class);
} else if (compare(PREPARE_STATEMENT, name)) {
// prepareStatement
constructor = getConstructor(PREPARE_STATEMENT_IDX, PreparedStatement.class);
sql = (String)args[0];
} else if (compare(PREPARE_CALL, name)) {
// prepareCall
constructor = getConstructor(PREPARE_CALL_IDX, CallableStatement.class);
sql = (String)args[0];
} else {
// do nothing
return statement;
}
return constructor.newInstance(new Object[] { new StatementProxy(statement,sql) });
} catch (Exception x) {
logger.warn("Unable to create statement proxy.", x);
}
return statement;
}
/**
* Class to measure query execute time.
*/
protected class StatementProxy implements InvocationHandler {
protected boolean closed = false;
protected Object delegate;
protected final String query;
public StatementProxy(Object parent, String query) {
this.delegate = parent;
this.query = query;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (compare(TOSTRING_VAL,method)) {
return toString();
}
if (compare(EQUALS_VAL, method)) {
return Boolean.valueOf(
this.equals(Proxy.getInvocationHandler(args[0])));
}
if (compare(HASHCODE_VAL, method)) {
return Integer.valueOf(this.hashCode());
}
if (compare(CLOSE_VAL, method)) {
if (delegate == null) return null;
}
if (compare(ISCLOSED_VAL, method)) {
if (delegate == null) return Boolean.TRUE;
}
if (delegate == null) throw new SQLException("Statement closed.");
Object result = null;
try {
//invoke next
result = method.invoke(delegate,args);
} catch (Throwable t) {
if (t instanceof InvocationTargetException && t.getCause() != null) {
throw t.getCause();
} else {
throw t;
}
}
//perform close cleanup
if (compare(CLOSE_VAL, method)) {
delegate = null;
}
return result;
}
@Override
public int hashCode() {
return System.identityHashCode(this);
}
@Override
public boolean equals(Object obj) {
return this==obj;
}
@Override
public String toString() {
StringBuffer buf = new StringBuffer(StatementProxy.class.getName());
buf.append("[Proxy=");
buf.append(hashCode());
buf.append("; Query=");
buf.append(query);
buf.append("; Delegate=");
buf.append(delegate);
buf.append("]");
return buf.toString();
}
}
}