| /* |
| * 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.InvocationHandler; |
| import java.lang.reflect.Method; |
| import java.util.Map; |
| |
| import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorProperty; |
| |
| /** |
| * Abstract class that is to be extended for implementations of interceptors. |
| * Everytime an operation is called on the {@link java.sql.Connection} object the |
| * {@link #invoke(Object, Method, Object[])} method on the interceptor will be called. |
| * Interceptors are useful to change or improve behavior of the connection pool.<br> |
| * Interceptors can receive a set of properties. Each sub class is responsible for parsing the properties during runtime when they |
| * are needed or simply override the {@link #setProperties(Map)} method. |
| * Properties arrive in a key-value pair of Strings as they were received through the configuration. |
| * This method is called once per cached connection object when the object is first configured. |
| * |
| * @version 1.0 |
| */ |
| public abstract class JdbcInterceptor implements InvocationHandler { |
| /** |
| * {@link java.sql.Connection#close()} method name |
| */ |
| public static final String CLOSE_VAL = "close"; |
| /** |
| * {@link Object#toString()} method name |
| */ |
| public static final String TOSTRING_VAL = "toString"; |
| /** |
| * {@link java.sql.Connection#isClosed()} method name |
| */ |
| public static final String ISCLOSED_VAL = "isClosed"; |
| /** |
| * {@link javax.sql.PooledConnection#getConnection()} method name |
| */ |
| public static final String GETCONNECTION_VAL = "getConnection"; |
| /** |
| * {@link java.sql.Wrapper#unwrap(Class)} method name |
| */ |
| public static final String UNWRAP_VAL = "unwrap"; |
| /** |
| * {@link java.sql.Wrapper#isWrapperFor(Class)} method name |
| */ |
| public static final String ISWRAPPERFOR_VAL = "isWrapperFor"; |
| |
| /** |
| * {@link java.sql.Connection#isValid(int)} method name |
| */ |
| public static final String ISVALID_VAL = "isValid"; |
| |
| /** |
| * {@link java.lang.Object#equals(Object)} |
| */ |
| public static final String EQUALS_VAL = "equals"; |
| |
| /** |
| * {@link java.lang.Object#hashCode()} |
| */ |
| public static final String HASHCODE_VAL = "hashCode"; |
| |
| /** |
| * Properties for this interceptor. |
| */ |
| protected Map<String,InterceptorProperty> properties = null; |
| |
| /** |
| * The next interceptor in the chain |
| */ |
| private volatile JdbcInterceptor next = null; |
| /** |
| * Property that decides how we do string comparison, default is to use |
| * {@link String#equals(Object)}. If set to <code>false</code> then the |
| * equality operator (==) is used. |
| */ |
| private boolean useEquals = true; |
| |
| /** |
| * Public constructor for instantiation through reflection |
| */ |
| public JdbcInterceptor() { |
| // NOOP |
| } |
| |
| /** |
| * Gets invoked each time an operation on {@link java.sql.Connection} is invoked. |
| * {@inheritDoc} |
| */ |
| |
| @Override |
| public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { |
| if (getNext()!=null) return getNext().invoke(proxy,method,args); |
| else throw new NullPointerException(); |
| } |
| |
| /** |
| * Returns the next interceptor in the chain |
| * @return the next interceptor in the chain |
| */ |
| public JdbcInterceptor getNext() { |
| return next; |
| } |
| |
| /** |
| * configures the next interceptor in the chain |
| * @param next |
| */ |
| public void setNext(JdbcInterceptor next) { |
| this.next = next; |
| } |
| |
| /** |
| * Performs a string comparison, using references unless the useEquals property is set to true. |
| * @param name1 |
| * @param name2 |
| * @return true if name1 is equal to name2 based on {@link #useEquals} |
| */ |
| public boolean compare(String name1, String name2) { |
| if (isUseEquals()) { |
| return name1.equals(name2); |
| } else { |
| return name1==name2; |
| } |
| } |
| |
| /** |
| * Compares a method name (String) to a method (Method) |
| * {@link #compare(String,String)} |
| * Uses reference comparison unless the useEquals property is set to true |
| * @param methodName |
| * @param method |
| * @return true if the name matches |
| */ |
| public boolean compare(String methodName, Method method) { |
| return compare(methodName, method.getName()); |
| } |
| |
| /** |
| * Gets called each time the connection is borrowed from the pool |
| * This means that if an interceptor holds a reference to the connection |
| * the interceptor can be reused for another connection. |
| * <br> |
| * This method may be called with null as both arguments when we are closing down the connection. |
| * @param parent - the connection pool owning the connection |
| * @param con - the pooled connection |
| */ |
| public abstract void reset(ConnectionPool parent, PooledConnection con); |
| |
| /** |
| * Called when {@link java.sql.Connection#close()} is called on the underlying connection. |
| * This is to notify the interceptors, that the physical connection has been released. |
| * Implementation of this method should be thought through with care, as no actions should trigger an exception. |
| * @param parent - the connection pool that this connection belongs to |
| * @param con - the pooled connection that holds this connection |
| * @param finalizing - if this connection is finalizing. True means that the pooled connection will not reconnect the underlying connection |
| */ |
| public void disconnected(ConnectionPool parent, PooledConnection con, boolean finalizing) { |
| } |
| |
| |
| /** |
| * Returns the properties configured for this interceptor |
| * @return the configured properties for this interceptor |
| */ |
| public Map<String,InterceptorProperty> getProperties() { |
| return properties; |
| } |
| |
| /** |
| * Called during the creation of an interceptor |
| * The properties can be set during the configuration of an interceptor |
| * Override this method to perform type casts between string values and object properties |
| * @param properties |
| */ |
| public void setProperties(Map<String,InterceptorProperty> properties) { |
| this.properties = properties; |
| final String useEquals = "useEquals"; |
| InterceptorProperty p = properties.get(useEquals); |
| if (p!=null) { |
| setUseEquals(Boolean.parseBoolean(p.getValue())); |
| } |
| } |
| |
| /** |
| * @return true if the compare method uses the Object.equals(Object) method |
| * false if comparison is done on a reference level |
| */ |
| public boolean isUseEquals() { |
| return useEquals; |
| } |
| |
| /** |
| * Set to true if string comparisons (for the {@link #compare(String, Method)} and {@link #compare(String, String)} methods) should use the Object.equals(Object) method |
| * The default is false |
| * @param useEquals |
| */ |
| public void setUseEquals(boolean useEquals) { |
| this.useEquals = useEquals; |
| } |
| |
| /** |
| * This method is invoked by a connection pool when the pool is closed. |
| * Interceptor classes can override this method if they keep static |
| * variables or other tracking means around. |
| * <b>This method is only invoked on a single instance of the interceptor, and not on every instance created.</b> |
| * @param pool - the pool that is being closed. |
| */ |
| public void poolClosed(ConnectionPool pool) { |
| // NOOP |
| } |
| |
| /** |
| * This method is invoked by a connection pool when the pool is first started up, usually when the first connection is requested. |
| * Interceptor classes can override this method if they keep static |
| * variables or other tracking means around. |
| * <b>This method is only invoked on a single instance of the interceptor, and not on every instance created.</b> |
| * @param pool - the pool that is being closed. |
| */ |
| public void poolStarted(ConnectionPool pool) { |
| // NOOP |
| } |
| |
| } |