| /* |
| * 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(); |
| } |
| } |
| |
| } |