[SDNC-5] Rebase sdnc-core
[sdnc/core.git] / dblib / common / src / main / java / org / apache / tomcat / jdbc / pool / JdbcInterceptor.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * openecomp
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
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
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=========================================================
19  */
20
21 /*
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
28  *
29  *      http://www.apache.org/licenses/LICENSE-2.0
30  *
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.
36  */
37 package org.apache.tomcat.jdbc.pool;
38
39 import java.lang.reflect.InvocationHandler;
40 import java.lang.reflect.Method;
41 import java.util.Map;
42
43 import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorProperty;
44
45 /**
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.
54  *
55  * @version 1.0
56  */
57 public abstract class JdbcInterceptor implements InvocationHandler {
58     /**
59      * {@link java.sql.Connection#close()} method name
60      */
61     public static final String CLOSE_VAL = "close";
62     /**
63      * {@link Object#toString()} method name
64      */
65     public static final String TOSTRING_VAL = "toString";
66     /**
67      * {@link java.sql.Connection#isClosed()} method name
68      */
69     public static final String ISCLOSED_VAL = "isClosed";
70     /**
71      * {@link javax.sql.PooledConnection#getConnection()} method name
72      */
73     public static final String GETCONNECTION_VAL = "getConnection";
74     /**
75      * {@link java.sql.Wrapper#unwrap(Class)} method name
76      */
77     public static final String UNWRAP_VAL = "unwrap";
78     /**
79      * {@link java.sql.Wrapper#isWrapperFor(Class)} method name
80      */
81     public static final String ISWRAPPERFOR_VAL = "isWrapperFor";
82
83     /**
84      * {@link java.sql.Connection#isValid(int)} method name
85      */
86     public static final String ISVALID_VAL = "isValid";
87
88     /**
89      * {@link java.lang.Object#equals(Object)}
90      */
91     public static final String EQUALS_VAL = "equals";
92
93     /**
94      * {@link java.lang.Object#hashCode()}
95      */
96     public static final String HASHCODE_VAL = "hashCode";
97
98     /**
99      * Properties for this interceptor.
100      */
101     protected Map<String,InterceptorProperty> properties = null;
102
103     /**
104      * The next interceptor in the chain
105      */
106     private volatile JdbcInterceptor next = null;
107     /**
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.
111      */
112     private boolean useEquals = true;
113
114     /**
115      * Public constructor for instantiation through reflection
116      */
117     public JdbcInterceptor() {
118         // NOOP
119     }
120
121     /**
122      * Gets invoked each time an operation on {@link java.sql.Connection} is invoked.
123      * {@inheritDoc}
124      */
125
126     @Override
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();
130     }
131
132     /**
133      * Returns the next interceptor in the chain
134      * @return the next interceptor in the chain
135      */
136     public JdbcInterceptor getNext() {
137         return next;
138     }
139
140     /**
141      * configures the next interceptor in the chain
142      * @param next The next chain item
143      */
144     public void setNext(JdbcInterceptor next) {
145         this.next = next;
146     }
147
148     /**
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}
153      */
154     public boolean compare(String name1, String name2) {
155         if (isUseEquals()) {
156             return name1.equals(name2);
157         } else {
158             return name1==name2;
159         }
160     }
161
162     /**
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
169      */
170     public boolean compare(String methodName, Method method) {
171         return compare(methodName, method.getName());
172     }
173
174     /**
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.
178      * <br>
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
182      */
183     public abstract void reset(ConnectionPool parent, PooledConnection con);
184
185     /**
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
192      */
193     public void disconnected(ConnectionPool parent, PooledConnection con, boolean finalizing) {
194     }
195
196
197     /**
198      * Returns the properties configured for this interceptor
199      * @return the configured properties for this interceptor
200      */
201     public Map<String,InterceptorProperty> getProperties() {
202         return properties;
203     }
204
205     /**
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
210      */
211     public void setProperties(Map<String,InterceptorProperty> properties) {
212         this.properties = properties;
213         final String useEquals = "useEquals";
214         InterceptorProperty p = properties.get(useEquals);
215         if (p!=null) {
216             setUseEquals(Boolean.parseBoolean(p.getValue()));
217         }
218     }
219
220     /**
221      * @return true if the compare method uses the Object.equals(Object) method
222      *         false if comparison is done on a reference level
223      */
224     public boolean isUseEquals() {
225         return useEquals;
226     }
227
228     /**
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
232      */
233     public void setUseEquals(boolean useEquals) {
234         this.useEquals = useEquals;
235     }
236
237     /**
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.
243      */
244     public void poolClosed(ConnectionPool pool) {
245         // NOOP
246     }
247
248     /**
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.
254      */
255     public void poolStarted(ConnectionPool pool) {
256         // NOOP
257     }
258
259 }