[SDNC-5] Rebase sdnc-core
[sdnc/core.git] / dblib / common / src / main / java / org / apache / tomcat / jdbc / pool / interceptor / StatementFinalizer.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.interceptor;
38
39 import java.lang.ref.WeakReference;
40 import java.lang.reflect.Method;
41 import java.sql.Statement;
42 import java.util.LinkedList;
43 import java.util.List;
44 import java.util.Map;
45
46 import org.apache.juli.logging.Log;
47 import org.apache.juli.logging.LogFactory;
48 import org.apache.tomcat.jdbc.pool.ConnectionPool;
49 import org.apache.tomcat.jdbc.pool.PoolProperties;
50 import org.apache.tomcat.jdbc.pool.PooledConnection;
51
52 /**
53  * Keeps track of statements associated with a connection and invokes close upon {@link java.sql.Connection#close()}
54  * Useful for applications that dont close the associated statements after being done with a connection.
55  *
56  */
57 public class StatementFinalizer extends AbstractCreateStatementInterceptor {
58     private static final Log log = LogFactory.getLog(StatementFinalizer.class);
59
60     protected List<StatementEntry> statements = new LinkedList<>();
61
62     private boolean logCreationStack = false;
63
64     @Override
65     public Object createStatement(Object proxy, Method method, Object[] args, Object statement, long time) {
66         try {
67             if (statement instanceof Statement)
68                 statements.add(new StatementEntry((Statement)statement));
69         }catch (ClassCastException x) {
70             //ignore this one
71         }
72         return statement;
73     }
74
75     @SuppressWarnings("null") // st is not null when used
76     @Override
77     public void closeInvoked() {
78         while (statements.size()>0) {
79             StatementEntry ws = statements.remove(0);
80             Statement st = ws.getStatement();
81             boolean shallClose = false;
82             try {
83                 shallClose = st!=null && (!st.isClosed());
84                 if (shallClose) {
85                     st.close();
86                 }
87             } catch (Exception ignore) {
88                 if (log.isDebugEnabled()) {
89                     log.debug("Unable to closed statement upon connection close.",ignore);
90                 }
91             } finally {
92                 if (logCreationStack && shallClose) {
93                     log.warn("Statement created, but was not closed at:", ws.getAllocationStack());
94                 }
95             }
96         }
97     }
98
99     @Override
100     public void setProperties(Map<String, PoolProperties.InterceptorProperty> properties) {
101         super.setProperties(properties);
102
103         PoolProperties.InterceptorProperty logProperty = properties.get("trace");
104         if (null != logProperty) {
105             logCreationStack = logProperty.getValueAsBoolean(logCreationStack);
106         }
107     }
108
109     @Override
110     public void reset(ConnectionPool parent, PooledConnection con) {
111         statements.clear();
112         super.reset(parent, con);
113     }
114
115     protected class StatementEntry {
116         private WeakReference<Statement> statement;
117         private Throwable allocationStack;
118
119         public StatementEntry(Statement statement) {
120             this.statement = new WeakReference<>(statement);
121             if (logCreationStack) {
122                 this.allocationStack = new Throwable();
123             }
124         }
125
126         public Statement getStatement() {
127             return statement.get();
128         }
129
130         public Throwable getAllocationStack() {
131             return allocationStack;
132         }
133     }
134
135
136 }