2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2016 - 2017 AT&T
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
22 * Licensed to the Apache Software Foundation (ASF) under one or more
23 * contributor license agreements. See the NOTICE file distributed with
24 * this work for additional information regarding copyright ownership.
25 * The ASF licenses this file to You under the Apache License, Version 2.0
26 * (the "License"); you may not use this file except in compliance with
27 * the License. You may obtain a copy of the License at
29 * http://www.apache.org/licenses/LICENSE-2.0
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
37 package org.apache.tomcat.jdbc.pool;
39 import java.lang.reflect.InvocationHandler;
40 import java.lang.reflect.Method;
43 import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorProperty;
46 * Abstract class that is to be extended for implementations of interceptors.
47 * Everytime an operation is called on the {@link java.sql.Connection} object the
48 * {@link #invoke(Object, Method, Object[])} method on the interceptor will be called.
49 * Interceptors are useful to change or improve behavior of the connection pool.<br>
50 * Interceptors can receive a set of properties. Each sub class is responsible for parsing the properties during runtime when they
51 * are needed or simply override the {@link #setProperties(Map)} method.
52 * Properties arrive in a key-value pair of Strings as they were received through the configuration.
53 * This method is called once per cached connection object when the object is first configured.
57 public abstract class JdbcInterceptor implements InvocationHandler {
59 * {@link java.sql.Connection#close()} method name
61 public static final String CLOSE_VAL = "close";
63 * {@link Object#toString()} method name
65 public static final String TOSTRING_VAL = "toString";
67 * {@link java.sql.Connection#isClosed()} method name
69 public static final String ISCLOSED_VAL = "isClosed";
71 * {@link javax.sql.PooledConnection#getConnection()} method name
73 public static final String GETCONNECTION_VAL = "getConnection";
75 * {@link java.sql.Wrapper#unwrap(Class)} method name
77 public static final String UNWRAP_VAL = "unwrap";
79 * {@link java.sql.Wrapper#isWrapperFor(Class)} method name
81 public static final String ISWRAPPERFOR_VAL = "isWrapperFor";
84 * {@link java.sql.Connection#isValid(int)} method name
86 public static final String ISVALID_VAL = "isValid";
89 * {@link java.lang.Object#equals(Object)}
91 public static final String EQUALS_VAL = "equals";
94 * {@link java.lang.Object#hashCode()}
96 public static final String HASHCODE_VAL = "hashCode";
99 * Properties for this interceptor.
101 protected Map<String,InterceptorProperty> properties = null;
104 * The next interceptor in the chain
106 private volatile JdbcInterceptor next = null;
108 * Property that decides how we do string comparison, default is to use
109 * {@link String#equals(Object)}. If set to <code>false</code> then the
110 * equality operator (==) is used.
112 private boolean useEquals = true;
115 * Public constructor for instantiation through reflection
117 public JdbcInterceptor() {
122 * Gets invoked each time an operation on {@link java.sql.Connection} is invoked.
127 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
128 if (getNext()!=null) return getNext().invoke(proxy,method,args);
129 else throw new NullPointerException();
133 * Returns the next interceptor in the chain
134 * @return the next interceptor in the chain
136 public JdbcInterceptor getNext() {
141 * configures the next interceptor in the chain
142 * @param next The next chain item
144 public void setNext(JdbcInterceptor next) {
149 * Performs a string comparison, using references unless the useEquals property is set to true.
150 * @param name1 The first name
151 * @param name2 The second name
152 * @return true if name1 is equal to name2 based on {@link #useEquals}
154 public boolean compare(String name1, String name2) {
156 return name1.equals(name2);
163 * Compares a method name (String) to a method (Method)
164 * {@link #compare(String,String)}
165 * Uses reference comparison unless the useEquals property is set to true
166 * @param methodName The method name
167 * @param method The method
168 * @return <code>true</code> if the name matches
170 public boolean compare(String methodName, Method method) {
171 return compare(methodName, method.getName());
175 * Gets called each time the connection is borrowed from the pool
176 * This means that if an interceptor holds a reference to the connection
177 * the interceptor can be reused for another connection.
179 * This method may be called with null as both arguments when we are closing down the connection.
180 * @param parent - the connection pool owning the connection
181 * @param con - the pooled connection
183 public abstract void reset(ConnectionPool parent, PooledConnection con);
186 * Called when {@link java.sql.Connection#close()} is called on the underlying connection.
187 * This is to notify the interceptors, that the physical connection has been released.
188 * Implementation of this method should be thought through with care, as no actions should trigger an exception.
189 * @param parent - the connection pool that this connection belongs to
190 * @param con - the pooled connection that holds this connection
191 * @param finalizing - if this connection is finalizing. True means that the pooled connection will not reconnect the underlying connection
193 public void disconnected(ConnectionPool parent, PooledConnection con, boolean finalizing) {
198 * Returns the properties configured for this interceptor
199 * @return the configured properties for this interceptor
201 public Map<String,InterceptorProperty> getProperties() {
206 * Called during the creation of an interceptor
207 * The properties can be set during the configuration of an interceptor
208 * Override this method to perform type casts between string values and object properties
209 * @param properties The properties
211 public void setProperties(Map<String,InterceptorProperty> properties) {
212 this.properties = properties;
213 final String useEquals = "useEquals";
214 InterceptorProperty p = properties.get(useEquals);
216 setUseEquals(Boolean.parseBoolean(p.getValue()));
221 * @return true if the compare method uses the Object.equals(Object) method
222 * false if comparison is done on a reference level
224 public boolean isUseEquals() {
229 * 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
230 * The default is false
231 * @param useEquals <code>true</code> if equals will be used for comparisons
233 public void setUseEquals(boolean useEquals) {
234 this.useEquals = useEquals;
238 * This method is invoked by a connection pool when the pool is closed.
239 * Interceptor classes can override this method if they keep static
240 * variables or other tracking means around.
241 * <b>This method is only invoked on a single instance of the interceptor, and not on every instance created.</b>
242 * @param pool - the pool that is being closed.
244 public void poolClosed(ConnectionPool pool) {
249 * This method is invoked by a connection pool when the pool is first started up, usually when the first connection is requested.
250 * Interceptor classes can override this method if they keep static
251 * variables or other tracking means around.
252 * <b>This method is only invoked on a single instance of the interceptor, and not on every instance created.</b>
253 * @param pool - the pool that is being closed.
255 public void poolStarted(ConnectionPool pool) {