ASF Bugzilla – Attachment 27457 Details for
Bug 48392
jdbc-pool is not returning the proxied connection in resultSet and statement
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
A correction to the createDecorator() method in the interceptor
StatementDecoratorInterceptor.java (text/x-java), 10.27 KB, created by
Neil Clarke
on 2011-09-05 08:54:34 UTC
(
hide
)
Description:
A correction to the createDecorator() method in the interceptor
Filename:
MIME Type:
Creator:
Neil Clarke
Created:
2011-09-05 08:54:34 UTC
Size:
10.27 KB
patch
obsolete
>/* > * 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.interceptor; > >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.ResultSet; >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; > >/** > * Implementation of <b>JdbcInterceptor</b> that proxies resultSets and statements. > * @author Guillermo Fernandes > */ >public class StatementDecoratorInterceptor extends AbstractCreateStatementInterceptor { > > private static final Log logger = LogFactory.getLog(StatementDecoratorInterceptor.class); > > private static final String[] EXECUTE_QUERY_TYPES = { "executeQuery" }; > > /** > * the constructors that are used to create statement proxies > */ > protected static final Constructor<?>[] constructors = new Constructor[AbstractCreateStatementInterceptor.STATEMENT_TYPE_COUNT]; > > /** > * the constructor to create the resultSet proxies > */ > protected static Constructor<?> resultSetConstructor = null; > > @Override > public void closeInvoked() { > // nothing to do > } > > /** > * Creates a constructor for a proxy class, if one doesn't already exist > * > * @param idx > * - the index of the constructor > * @param clazz > * - the interface that the proxy will implement > * @return - returns a constructor used to create new instances > * @throws NoSuchMethodException > */ > protected Constructor<?> getConstructor(int idx, Class<?> clazz) throws NoSuchMethodException { > if (constructors[idx] == null) { > Class<?> proxyClass = Proxy.getProxyClass(StatementDecoratorInterceptor.class.getClassLoader(), > new Class[] { clazz }); > constructors[idx] = proxyClass.getConstructor(new Class[] { InvocationHandler.class }); > } > return constructors[idx]; > } > > protected Constructor<?> getResultSetConstructor() throws NoSuchMethodException { > if (resultSetConstructor == null) { > Class<?> proxyClass = Proxy.getProxyClass(StatementDecoratorInterceptor.class.getClassLoader(), > new Class[] { ResultSet.class }); > resultSetConstructor = proxyClass.getConstructor(new Class[] { InvocationHandler.class }); > } > return resultSetConstructor; > } > > /** > * 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, might be a future unsupported method > // so we better bail out and let the system continue > return statement; > } > return createDecorator(proxy, method, args, statement, constructor, sql); > } catch (Exception x) { > logger.warn("Unable to create statement proxy for slow query report.", x); > } > return statement; > } > > protected Object createDecorator(Object proxy, Method method, Object[] args, > Object statement, Constructor<?> constructor, String sql) > throws InstantiationException, IllegalAccessException, InvocationTargetException { > Object result = null; > StatementProxy statementProxy = new StatementProxy<Statement>((Statement)statement,sql); > result = constructor.newInstance(new Object[] { statementProxy }); > statementProxy.setActualProxy(result); > statementProxy.setConnection(proxy); > statementProxy.setConstructor(constructor); > return result; > } > > protected boolean isExecuteQuery(String methodName) { > return EXECUTE_QUERY_TYPES[0].equals(methodName); > } > > protected boolean isExecuteQuery(Method method) { > return isExecuteQuery(method.getName()); > } > > /** > * Class to measure query execute time > * > * @author fhanik > * > */ > protected class StatementProxy<T extends java.sql.Statement> implements InvocationHandler { > > protected boolean closed = false; > protected T delegate; > private Object actualProxy; > private Object connection; > private String sql; > private Constructor constructor; > > public StatementProxy(T delegate, String sql) { > this.delegate = delegate; > this.sql = sql; > } > public T getDelegate() { > return this.delegate; > } > > public String getSql() { > return sql; > } > > public void setConnection(Object proxy) { > this.connection = proxy; > } > public Object getConnection() { > return this.connection; > } > > public void setActualProxy(Object proxy){ > this.actualProxy = proxy; > } > public Object getActualProxy() { > return this.actualProxy; > } > > > public Constructor getConstructor() { > return constructor; > } > public void setConstructor(Constructor constructor) { > this.constructor = constructor; > } > public void closeInvoked() { > if (getDelegate()!=null) { > try { > getDelegate().close(); > }catch (SQLException ignore) { > } > } > closed = true; > delegate = null; > } > > public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { > if (compare(TOSTRING_VAL,method)) { > return toString(); > } > // was close invoked? > boolean close = compare(CLOSE_VAL, method); > // allow close to be called multiple times > if (close && closed) > return null; > // are we calling isClosed? > if (compare(ISCLOSED_VAL, method)) > return Boolean.valueOf(closed); > // if we are calling anything else, bail out > if (closed) > throw new SQLException("Statement closed."); > if (compare(GETCONNECTION_VAL,method)){ > return connection; > } > boolean process = isExecuteQuery(method); > // check to see if we are about to execute a query > // if we are executing, get the current time > Object result = null; > try { > // perform close cleanup > if (close) { > closeInvoked(); > } else { > // execute the query > result = method.invoke(delegate, args); > } > } catch (Throwable t) { > if (t instanceof InvocationTargetException) { > InvocationTargetException it = (InvocationTargetException) t; > throw it.getCause() != null ? it.getCause() : it; > } else { > throw t; > } > } > if (process){ > Constructor<?> cons = getResultSetConstructor(); > result = cons.newInstance(new Object[]{new ResultSetProxy(actualProxy, result)}); > } > return result; > } > > public String toString() { > StringBuffer buf = new StringBuffer(StatementProxy.class.getName()); > buf.append("[Proxy="); > buf.append(System.identityHashCode(this)); > buf.append("; Sql="); > buf.append(getSql()); > buf.append("; Delegate="); > buf.append(getDelegate()); > buf.append("; Connection="); > buf.append(getConnection()); > buf.append("]"); > return buf.toString(); > } > } > > protected class ResultSetProxy implements InvocationHandler { > > private Object st; > private Object delegate; > > public ResultSetProxy(Object st, Object delegate) { > this.st = st; > this.delegate = delegate; > } > > public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { > if (method.getName().equals("getStatement")) { > return this.st; > } else { > return method.invoke(this.delegate, args); > } > } > } >}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 48392
:
24713
|
25054
| 27457