View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.dbcp2.datasources;
19  
20  import java.sql.Connection;
21  import java.sql.SQLException;
22  import java.util.ArrayList;
23  import java.util.Collection;
24  import java.util.Collections;
25  import java.util.EventListener;
26  import java.util.List;
27  
28  import javax.sql.ConnectionEvent;
29  import javax.sql.ConnectionEventListener;
30  import javax.sql.PooledConnection;
31  import javax.sql.StatementEventListener;
32  
33  /**
34   * PooledConnection implementation that wraps a driver-supplied
35   * PooledConnection and proxies events, allowing behavior to be
36   * modified to simulate behavior of different implementations.
37   */
38  public class PooledConnectionProxy implements PooledConnection,
39      ConnectionEventListener {
40  
41      protected PooledConnection delegate;
42  
43      /**
44       * ConnectionEventListeners
45       */
46      private final List<EventListener> eventListeners = Collections.synchronizedList(new ArrayList<>());
47  
48      /**
49       * True means we will (dubiously) notify listeners with a
50       * ConnectionClosed event when this (i.e. the PooledConnection itself)
51       * is closed
52       */
53      private boolean notifyOnClose;
54  
55      public PooledConnectionProxy(final PooledConnection pooledConnection) {
56          this.delegate = pooledConnection;
57          pooledConnection.addConnectionEventListener(this);
58      }
59  
60      /**
61       * Add event listeners.
62       */
63      @Override
64      public void addConnectionEventListener(final ConnectionEventListener listener) {
65          if (!eventListeners.contains(listener)) {
66              eventListeners.add(listener);
67          }
68      }
69  
70      @Override
71      public void addStatementEventListener(final StatementEventListener listener) {
72          if (!eventListeners.contains(listener)) {
73              eventListeners.add(listener);
74          }
75      }
76  
77      /**
78       * If notifyOnClose is on, notify listeners
79       */
80      @Override
81      public void close() throws SQLException {
82          delegate.close();
83          if (isNotifyOnClose()) {
84             notifyListeners();
85          }
86      }
87  
88      /**
89       * Pass closed events on to listeners
90       */
91      @Override
92      public void connectionClosed(final ConnectionEvent event) {
93          notifyListeners();
94      }
95  
96      /**
97       * Pass error events on to listeners
98       */
99      @Override
100     public void connectionErrorOccurred(final ConnectionEvent event) {
101         final Object[] listeners = eventListeners.toArray();
102         for (final Object listener : listeners) {
103             ((ConnectionEventListener) listener).connectionErrorOccurred(event);
104         }
105     }
106 
107     @Override
108     public Connection getConnection() throws SQLException {
109         return delegate.getConnection();
110     }
111 
112     /**
113      * Expose listeners
114      */
115     public Collection<EventListener> getListeners() {
116         return eventListeners;
117     }
118 
119     public boolean isNotifyOnClose() {
120         return notifyOnClose;
121     }
122 
123     /**
124      * sends a connectionClosed event to listeners.
125      */
126     void notifyListeners() {
127         final ConnectionEvent event = new ConnectionEvent(this);
128         final Object[] listeners = eventListeners.toArray();
129         for (final Object listener : listeners) {
130             ((ConnectionEventListener) listener).connectionClosed(event);
131         }
132     }
133 
134     /**
135      * Remove event listeners.
136      */
137     @Override
138     public void removeConnectionEventListener(final ConnectionEventListener listener) {
139         eventListeners.remove(listener);
140     }
141 
142     @Override
143     public void removeStatementEventListener(final StatementEventListener listener) {
144         eventListeners.remove(listener);
145     }
146 
147     public void setNotifyOnClose(final boolean notifyOnClose) {
148         this.notifyOnClose = notifyOnClose;
149     }
150 
151     /**
152      * Generate a connection error event
153      */
154     public void throwConnectionError() {
155         final ConnectionEvent event = new ConnectionEvent(this);
156         connectionErrorOccurred(event);
157     }
158 
159 }