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.interceptor;
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;
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;
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.
57 public class StatementFinalizer extends AbstractCreateStatementInterceptor {
58 private static final Log log = LogFactory.getLog(StatementFinalizer.class);
60 protected List<StatementEntry> statements = new LinkedList<>();
62 private boolean logCreationStack = false;
65 public Object createStatement(Object proxy, Method method, Object[] args, Object statement, long time) {
67 if (statement instanceof Statement)
68 statements.add(new StatementEntry((Statement)statement));
69 }catch (ClassCastException x) {
75 @SuppressWarnings("null") // st is not null when used
77 public void closeInvoked() {
78 while (statements.size()>0) {
79 StatementEntry ws = statements.remove(0);
80 Statement st = ws.getStatement();
81 boolean shallClose = false;
83 shallClose = st!=null && (!st.isClosed());
87 } catch (Exception ignore) {
88 if (log.isDebugEnabled()) {
89 log.debug("Unable to closed statement upon connection close.",ignore);
92 if (logCreationStack && shallClose) {
93 log.warn("Statement created, but was not closed at:", ws.getAllocationStack());
100 public void setProperties(Map<String, PoolProperties.InterceptorProperty> properties) {
101 super.setProperties(properties);
103 PoolProperties.InterceptorProperty logProperty = properties.get("trace");
104 if (null != logProperty) {
105 logCreationStack = logProperty.getValueAsBoolean(logCreationStack);
110 public void reset(ConnectionPool parent, PooledConnection con) {
112 super.reset(parent, con);
115 protected class StatementEntry {
116 private WeakReference<Statement> statement;
117 private Throwable allocationStack;
119 public StatementEntry(Statement statement) {
120 this.statement = new WeakReference<>(statement);
121 if (logCreationStack) {
122 this.allocationStack = new Throwable();
126 public Statement getStatement() {
127 return statement.get();
130 public Throwable getAllocationStack() {
131 return allocationStack;