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.InvocationTargetException;
40 import java.lang.reflect.Method;
41 import java.sql.SQLException;
43 import javax.sql.XAConnection;
45 * A ProxyConnection object is the bottom most interceptor that wraps an object of type
46 * {@link PooledConnection}. The ProxyConnection intercepts three methods:
48 * <li>{@link java.sql.Connection#close()} - returns the connection to the pool. May be called multiple times.</li>
49 * <li>{@link java.lang.Object#toString()} - returns a custom string for this object</li>
50 * <li>{@link javax.sql.PooledConnection#getConnection()} - returns the underlying connection</li>
52 * By default method comparisons is done on a String reference level, unless the {@link PoolConfiguration#setUseEquals(boolean)} has been called
53 * with a <code>true</code> argument.
55 public class ProxyConnection extends JdbcInterceptor {
57 protected PooledConnection connection = null;
59 protected ConnectionPool pool = null;
61 public PooledConnection getConnection() {
65 public void setConnection(PooledConnection connection) {
66 this.connection = connection;
69 public ConnectionPool getPool() {
73 public void setPool(ConnectionPool pool) {
77 protected ProxyConnection(ConnectionPool parent, PooledConnection con,
81 setUseEquals(useEquals);
85 public void reset(ConnectionPool parent, PooledConnection con) {
87 this.connection = con;
90 public boolean isWrapperFor(Class<?> iface) {
91 if (iface == XAConnection.class && connection.getXAConnection()!=null) {
94 return (iface.isInstance(connection.getConnection()));
99 public Object unwrap(Class<?> iface) throws SQLException {
100 if (iface == PooledConnection.class) {
102 }else if (iface == XAConnection.class) {
103 return connection.getXAConnection();
104 } else if (isWrapperFor(iface)) {
105 return connection.getConnection();
107 throw new SQLException("Not a wrapper of "+iface.getName());
112 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
113 if (compare(ISCLOSED_VAL,method)) {
114 return Boolean.valueOf(isClosed());
116 if (compare(CLOSE_VAL,method)) {
117 if (connection==null) return null; //noop for already closed.
118 PooledConnection poolc = this.connection;
119 this.connection = null;
120 pool.returnConnection(poolc);
122 } else if (compare(TOSTRING_VAL,method)) {
123 return this.toString();
124 } else if (compare(GETCONNECTION_VAL,method) && connection!=null) {
125 return connection.getConnection();
126 } else if (method.getDeclaringClass().equals(XAConnection.class)) {
128 return method.invoke(connection.getXAConnection(),args);
129 }catch (Throwable t) {
130 if (t instanceof InvocationTargetException) {
131 throw t.getCause() != null ? t.getCause() : t;
137 if (isClosed()) throw new SQLException("Connection has already been closed.");
138 if (compare(UNWRAP_VAL,method)) {
139 return unwrap((Class<?>)args[0]);
140 } else if (compare(ISWRAPPERFOR_VAL,method)) {
141 return Boolean.valueOf(this.isWrapperFor((Class<?>)args[0]));
144 PooledConnection poolc = connection;
146 return method.invoke(poolc.getConnection(),args);
148 throw new SQLException("Connection has already been closed.");
150 }catch (Throwable t) {
151 if (t instanceof InvocationTargetException) {
152 throw t.getCause() != null ? t.getCause() : t;
159 public boolean isClosed() {
160 return connection==null || connection.isDiscarded();
163 public PooledConnection getDelegateConnection() {
167 public ConnectionPool getParentPool() {
172 public String toString() {
173 return "ProxyConnection["+(connection!=null?connection.toString():"null")+"]";