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.io.PrintWriter;
40 import java.sql.Connection;
41 import java.sql.SQLException;
42 import java.sql.SQLFeatureNotSupportedException;
43 import java.util.Iterator;
44 import java.util.Properties;
45 import java.util.concurrent.Future;
46 import java.util.logging.Logger;
48 import javax.sql.XAConnection;
50 import org.apache.juli.logging.Log;
51 import org.apache.juli.logging.LogFactory;
52 import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorDefinition;
56 * The DataSource proxy lets us implements methods that don't exist in the current
57 * compiler JDK but might be methods that are part of a future JDK DataSource interface.
59 * It's a trick to work around compiler issues when implementing interfaces. For example,
60 * I could put in Java 6 methods of javax.sql.DataSource here, and compile it with JDK 1.5
61 * and still be able to run under Java 6 without getting NoSuchMethodException.
66 public class DataSourceProxy implements PoolConfiguration {
67 private static final Log log = LogFactory.getLog(DataSourceProxy.class);
69 protected volatile ConnectionPool pool = null;
71 protected volatile PoolConfiguration poolProperties = null;
73 public DataSourceProxy() {
74 this(new PoolProperties());
77 public DataSourceProxy(PoolConfiguration poolProperties) {
78 if (poolProperties == null) throw new NullPointerException("PoolConfiguration cannot be null.");
79 this.poolProperties = poolProperties;
83 @SuppressWarnings("unused") // Has to match signature in DataSource
84 public boolean isWrapperFor(Class<?> iface) throws SQLException {
85 // we are not a wrapper of anything
90 @SuppressWarnings("unused") // Has to match signature in DataSource
91 public <T> T unwrap(Class<T> iface) throws SQLException {
92 //we can't unwrap anything
97 * Get a database connection.
98 * {@link javax.sql.DataSource#getConnection()}
99 * @param username The user name
100 * @param password The password
101 * @return the connection
102 * @throws SQLException Connection error
104 public Connection getConnection(String username, String password) throws SQLException {
105 if (this.getPoolProperties().isAlternateUsernameAllowed()) {
107 return createPool().getConnection(username,password);
108 return pool.getConnection(username,password);
110 return getConnection();
114 public PoolConfiguration getPoolProperties() {
115 return poolProperties;
119 * Sets up the connection pool, by creating a pooling driver.
120 * @return the connection pool
121 * @throws SQLException Error creating pool
123 public ConnectionPool createPool() throws SQLException {
127 return pCreatePool();
132 * Sets up the connection pool, by creating a pooling driver.
134 private synchronized ConnectionPool pCreatePool() throws SQLException {
138 pool = new ConnectionPool(poolProperties);
144 * Get a database connection.
145 * {@link javax.sql.DataSource#getConnection()}
146 * @return the connection
147 * @throws SQLException Connection error
149 public Connection getConnection() throws SQLException {
151 return createPool().getConnection();
152 return pool.getConnection();
156 * Invokes an sync operation to retrieve the connection.
157 * @return a Future containing a reference to the connection when it becomes available
158 * @throws SQLException Connection error
160 public Future<Connection> getConnectionAsync() throws SQLException {
162 return createPool().getConnectionAsync();
163 return pool.getConnectionAsync();
167 * Get a database connection.
168 * {@link javax.sql.XADataSource#getXAConnection()}
169 * @return the connection
170 * @throws SQLException Connection error
172 public XAConnection getXAConnection() throws SQLException {
173 Connection con = getConnection();
174 if (con instanceof XAConnection) {
175 return (XAConnection)con;
179 } catch (Exception ignore) {
182 throw new SQLException("Connection from pool does not implement javax.sql.XAConnection");
187 * Get a database connection.
188 * {@link javax.sql.XADataSource#getXAConnection(String, String)}
189 * @param username The user name
190 * @param password The password
191 * @return the connection
192 * @throws SQLException Connection error
194 public XAConnection getXAConnection(String username, String password) throws SQLException {
195 Connection con = getConnection(username, password);
196 if (con instanceof XAConnection) {
197 return (XAConnection)con;
201 } catch (Exception ignore) {
204 throw new SQLException("Connection from pool does not implement javax.sql.XAConnection");
210 * Get a database connection.
211 * {@link javax.sql.DataSource#getConnection()}
212 * @return the connection
213 * @throws SQLException Connection error
215 public javax.sql.PooledConnection getPooledConnection() throws SQLException {
216 return (javax.sql.PooledConnection) getConnection();
220 * Get a database connection.
221 * {@link javax.sql.DataSource#getConnection()}
222 * @param username unused
223 * @param password unused
224 * @return the connection
225 * @throws SQLException Connection error
227 public javax.sql.PooledConnection getPooledConnection(String username,
228 String password) throws SQLException {
229 return (javax.sql.PooledConnection) getConnection();
232 public ConnectionPool getPool() {
235 }catch (SQLException x) {
236 log.error("Error during connection pool creation.", x);
242 public void close() {
245 public void close(boolean all) {
248 final ConnectionPool p = pool;
254 }catch (Exception x) {
255 log.warn("Error during connection pool closure.", x);
259 public int getPoolSize() {
260 final ConnectionPool p = pool;
261 if (p == null) return 0;
262 else return p.getSize();
267 public String toString() {
268 return super.toString()+"{"+getPoolProperties()+"}";
272 /*-----------------------------------------------------------------------*/
273 // PROPERTIES WHEN NOT USED WITH FACTORY
274 /*------------------------------------------------------------------------*/
281 public String getPoolName() {
282 return pool.getName();
286 public void setPoolProperties(PoolConfiguration poolProperties) {
287 this.poolProperties = poolProperties;
295 public void setDriverClassName(String driverClassName) {
296 this.poolProperties.setDriverClassName(driverClassName);
304 public void setInitialSize(int initialSize) {
305 this.poolProperties.setInitialSize(initialSize);
313 public void setInitSQL(String initSQL) {
314 this.poolProperties.setInitSQL(initSQL);
322 public void setLogAbandoned(boolean logAbandoned) {
323 this.poolProperties.setLogAbandoned(logAbandoned);
331 public void setMaxActive(int maxActive) {
332 this.poolProperties.setMaxActive(maxActive);
340 public void setMaxIdle(int maxIdle) {
341 this.poolProperties.setMaxIdle(maxIdle);
349 public void setMaxWait(int maxWait) {
350 this.poolProperties.setMaxWait(maxWait);
358 public void setMinEvictableIdleTimeMillis(int minEvictableIdleTimeMillis) {
359 this.poolProperties.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
367 public void setMinIdle(int minIdle) {
368 this.poolProperties.setMinIdle(minIdle);
376 public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) {
377 this.poolProperties.setNumTestsPerEvictionRun(numTestsPerEvictionRun);
385 public void setPassword(String password) {
386 this.poolProperties.setPassword(password);
387 this.poolProperties.getDbProperties().setProperty("password",this.poolProperties.getPassword());
395 public void setRemoveAbandoned(boolean removeAbandoned) {
396 this.poolProperties.setRemoveAbandoned(removeAbandoned);
404 public void setRemoveAbandonedTimeout(int removeAbandonedTimeout) {
405 this.poolProperties.setRemoveAbandonedTimeout(removeAbandonedTimeout);
413 public void setTestOnBorrow(boolean testOnBorrow) {
414 this.poolProperties.setTestOnBorrow(testOnBorrow);
422 public void setTestOnConnect(boolean testOnConnect) {
423 this.poolProperties.setTestOnConnect(testOnConnect);
431 public void setTestOnReturn(boolean testOnReturn) {
432 this.poolProperties.setTestOnReturn(testOnReturn);
440 public void setTestWhileIdle(boolean testWhileIdle) {
441 this.poolProperties.setTestWhileIdle(testWhileIdle);
449 public void setTimeBetweenEvictionRunsMillis(int timeBetweenEvictionRunsMillis) {
450 this.poolProperties.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
458 public void setUrl(String url) {
459 this.poolProperties.setUrl(url);
467 public void setUsername(String username) {
468 this.poolProperties.setUsername(username);
469 this.poolProperties.getDbProperties().setProperty("user",getPoolProperties().getUsername());
477 public void setValidationInterval(long validationInterval) {
478 this.poolProperties.setValidationInterval(validationInterval);
486 public void setValidationQuery(String validationQuery) {
487 this.poolProperties.setValidationQuery(validationQuery);
495 public void setValidatorClassName(String className) {
496 this.poolProperties.setValidatorClassName(className);
504 public void setValidationQueryTimeout(int validationQueryTimeout) {
505 this.poolProperties.setValidationQueryTimeout(validationQueryTimeout);
513 public void setJdbcInterceptors(String interceptors) {
514 this.getPoolProperties().setJdbcInterceptors(interceptors);
522 public void setJmxEnabled(boolean enabled) {
523 this.getPoolProperties().setJmxEnabled(enabled);
531 public void setFairQueue(boolean fairQueue) {
532 this.getPoolProperties().setFairQueue(fairQueue);
540 public void setUseLock(boolean useLock) {
541 this.getPoolProperties().setUseLock(useLock);
549 public void setDefaultCatalog(String catalog) {
550 this.getPoolProperties().setDefaultCatalog(catalog);
558 public void setDefaultAutoCommit(Boolean autocommit) {
559 this.getPoolProperties().setDefaultAutoCommit(autocommit);
567 public void setDefaultTransactionIsolation(int defaultTransactionIsolation) {
568 this.getPoolProperties().setDefaultTransactionIsolation(defaultTransactionIsolation);
576 public void setConnectionProperties(String properties) {
578 java.util.Properties prop = DataSourceFactory
579 .getProperties(properties);
580 Iterator<?> i = prop.keySet().iterator();
581 while (i.hasNext()) {
582 String key = (String) i.next();
583 String value = prop.getProperty(key);
584 getPoolProperties().getDbProperties().setProperty(key, value);
587 } catch (Exception x) {
588 log.error("Unable to parse connection properties.", x);
589 throw new RuntimeException(x);
598 public void setUseEquals(boolean useEquals) {
599 this.getPoolProperties().setUseEquals(useEquals);
604 * {@link javax.sql.DataSource#getParentLogger}
605 * @return no return value
606 * @throws SQLFeatureNotSupportedException Unsupported
608 public Logger getParentLogger() throws SQLFeatureNotSupportedException {
609 throw new SQLFeatureNotSupportedException();
614 * {@link javax.sql.DataSource#getLogWriter}
616 * @throws SQLException No exception
618 public PrintWriter getLogWriter() throws SQLException {
625 * {@link javax.sql.DataSource#setLogWriter(PrintWriter)}
627 * @throws SQLException No exception
629 public void setLogWriter(PrintWriter out) throws SQLException {
635 * {@link javax.sql.DataSource#getLoginTimeout}
636 * @return the timeout
638 public int getLoginTimeout() {
639 if (poolProperties == null) {
642 return poolProperties.getMaxWait() / 1000;
647 * {@link javax.sql.DataSource#setLoginTimeout(int)}
648 * @param i The timeout value
650 public void setLoginTimeout(int i) {
651 if (poolProperties == null) {
654 poolProperties.setMaxWait(1000 * i);
665 public int getSuspectTimeout() {
666 return getPoolProperties().getSuspectTimeout();
674 public void setSuspectTimeout(int seconds) {
675 getPoolProperties().setSuspectTimeout(seconds);
678 //===============================================================================
679 // Expose JMX attributes through Tomcat's dynamic reflection
680 //===============================================================================
682 * If the pool has not been created, it will be created during this call.
683 * @return the number of established but idle connections
685 public int getIdle() {
687 return createPool().getIdle();
688 }catch (SQLException x) {
689 throw new RuntimeException(x);
695 * @return the number of established but idle connections
697 public int getNumIdle() {
702 * Forces an abandon check on the connection pool.
703 * If connections that have been abandoned exists, they will be closed during this run
705 public void checkAbandoned() {
707 createPool().checkAbandoned();
708 }catch (SQLException x) {
709 throw new RuntimeException(x);
714 * Forces a check for resizing of the idle connections
716 public void checkIdle() {
718 createPool().checkIdle();
719 }catch (SQLException x) {
720 throw new RuntimeException(x);
725 * @return number of connections in use by the application
727 public int getActive() {
729 return createPool().getActive();
730 }catch (SQLException x) {
731 throw new RuntimeException(x);
736 * @return number of connections in use by the application
737 * {@link DataSource#getActive()}
739 public int getNumActive() {
744 * @return number of threads waiting for a connection
746 public int getWaitCount() {
748 return createPool().getWaitCount();
749 }catch (SQLException x) {
750 throw new RuntimeException(x);
755 * @return the current size of the pool
757 public int getSize() {
759 return createPool().getSize();
760 }catch (SQLException x) {
761 throw new RuntimeException(x);
766 * Performs a validation on idle connections
768 public void testIdle() {
770 createPool().testAllIdle();
771 }catch (SQLException x) {
772 throw new RuntimeException(x);
777 * The total number of connections borrowed from this pool.
778 * @return the borrowed connection count
780 public long getBorrowedCount() {
782 return createPool().getBorrowedCount();
783 } catch (SQLException x) {
784 throw new RuntimeException(x);
789 * The total number of connections returned to this pool.
790 * @return the returned connection count
792 public long getReturnedCount() {
794 return createPool().getReturnedCount();
795 } catch (SQLException x) {
796 throw new RuntimeException(x);
801 * The total number of connections created by this pool.
802 * @return the created connection count
804 public long getCreatedCount() {
806 return createPool().getCreatedCount();
807 } catch (SQLException x) {
808 throw new RuntimeException(x);
813 * The total number of connections released from this pool.
814 * @return the released connection count
816 public long getReleasedCount() {
818 return createPool().getReleasedCount();
819 } catch (SQLException x) {
820 throw new RuntimeException(x);
825 * The total number of connections reconnected by this pool.
826 * @return the reconnected connection count
828 public long getReconnectedCount() {
830 return createPool().getReconnectedCount();
831 } catch (SQLException x) {
832 throw new RuntimeException(x);
837 * The total number of connections released by remove abandoned.
838 * @return the PoolCleaner removed abandoned connection count
840 public long getRemoveAbandonedCount() {
842 return createPool().getRemoveAbandonedCount();
843 } catch (SQLException x) {
844 throw new RuntimeException(x);
849 * The total number of connections released by eviction.
850 * @return the PoolCleaner evicted idle connection count
852 public long getReleasedIdleCount() {
854 return createPool().getReleasedIdleCount();
855 } catch (SQLException x) {
856 throw new RuntimeException(x);
861 * reset the statistics of this pool.
863 public void resetStats() {
865 createPool().resetStats();
866 } catch (SQLException x) {
867 throw new RuntimeException(x);
871 //=========================================================
872 // PROPERTIES / CONFIGURATION
873 //=========================================================
880 public String getConnectionProperties() {
881 return getPoolProperties().getConnectionProperties();
889 public Properties getDbProperties() {
890 return getPoolProperties().getDbProperties();
898 public String getDefaultCatalog() {
899 return getPoolProperties().getDefaultCatalog();
907 public int getDefaultTransactionIsolation() {
908 return getPoolProperties().getDefaultTransactionIsolation();
916 public String getDriverClassName() {
917 return getPoolProperties().getDriverClassName();
926 public int getInitialSize() {
927 return getPoolProperties().getInitialSize();
935 public String getInitSQL() {
936 return getPoolProperties().getInitSQL();
944 public String getJdbcInterceptors() {
945 return getPoolProperties().getJdbcInterceptors();
953 public int getMaxActive() {
954 return getPoolProperties().getMaxActive();
962 public int getMaxIdle() {
963 return getPoolProperties().getMaxIdle();
971 public int getMaxWait() {
972 return getPoolProperties().getMaxWait();
980 public int getMinEvictableIdleTimeMillis() {
981 return getPoolProperties().getMinEvictableIdleTimeMillis();
989 public int getMinIdle() {
990 return getPoolProperties().getMinIdle();
998 public long getMaxAge() {
999 return getPoolProperties().getMaxAge();
1007 public String getName() {
1008 return getPoolProperties().getName();
1016 public int getNumTestsPerEvictionRun() {
1017 return getPoolProperties().getNumTestsPerEvictionRun();
1021 * @return DOES NOT RETURN THE PASSWORD, IT WOULD SHOW UP IN JMX
1024 public String getPassword() {
1025 return "Password not available as DataSource/JMX operation.";
1033 public int getRemoveAbandonedTimeout() {
1034 return getPoolProperties().getRemoveAbandonedTimeout();
1043 public int getTimeBetweenEvictionRunsMillis() {
1044 return getPoolProperties().getTimeBetweenEvictionRunsMillis();
1052 public String getUrl() {
1053 return getPoolProperties().getUrl();
1061 public String getUsername() {
1062 return getPoolProperties().getUsername();
1070 public long getValidationInterval() {
1071 return getPoolProperties().getValidationInterval();
1079 public String getValidationQuery() {
1080 return getPoolProperties().getValidationQuery();
1088 public int getValidationQueryTimeout() {
1089 return getPoolProperties().getValidationQueryTimeout();
1097 public String getValidatorClassName() {
1098 return getPoolProperties().getValidatorClassName();
1106 public Validator getValidator() {
1107 return getPoolProperties().getValidator();
1114 public void setValidator(Validator validator) {
1115 getPoolProperties().setValidator(validator);
1124 public boolean isAccessToUnderlyingConnectionAllowed() {
1125 return getPoolProperties().isAccessToUnderlyingConnectionAllowed();
1133 public Boolean isDefaultAutoCommit() {
1134 return getPoolProperties().isDefaultAutoCommit();
1142 public Boolean isDefaultReadOnly() {
1143 return getPoolProperties().isDefaultReadOnly();
1151 public boolean isLogAbandoned() {
1152 return getPoolProperties().isLogAbandoned();
1160 public boolean isPoolSweeperEnabled() {
1161 return getPoolProperties().isPoolSweeperEnabled();
1169 public boolean isRemoveAbandoned() {
1170 return getPoolProperties().isRemoveAbandoned();
1178 public int getAbandonWhenPercentageFull() {
1179 return getPoolProperties().getAbandonWhenPercentageFull();
1187 public boolean isTestOnBorrow() {
1188 return getPoolProperties().isTestOnBorrow();
1196 public boolean isTestOnConnect() {
1197 return getPoolProperties().isTestOnConnect();
1205 public boolean isTestOnReturn() {
1206 return getPoolProperties().isTestOnReturn();
1214 public boolean isTestWhileIdle() {
1215 return getPoolProperties().isTestWhileIdle();
1224 public Boolean getDefaultAutoCommit() {
1225 return getPoolProperties().getDefaultAutoCommit();
1233 public Boolean getDefaultReadOnly() {
1234 return getPoolProperties().getDefaultReadOnly();
1242 public InterceptorDefinition[] getJdbcInterceptorsAsArray() {
1243 return getPoolProperties().getJdbcInterceptorsAsArray();
1251 public boolean getUseLock() {
1252 return getPoolProperties().getUseLock();
1260 public boolean isFairQueue() {
1261 return getPoolProperties().isFairQueue();
1269 public boolean isJmxEnabled() {
1270 return getPoolProperties().isJmxEnabled();
1278 public boolean isUseEquals() {
1279 return getPoolProperties().isUseEquals();
1287 public void setAbandonWhenPercentageFull(int percentage) {
1288 getPoolProperties().setAbandonWhenPercentageFull(percentage);
1296 public void setAccessToUnderlyingConnectionAllowed(boolean accessToUnderlyingConnectionAllowed) {
1297 getPoolProperties().setAccessToUnderlyingConnectionAllowed(accessToUnderlyingConnectionAllowed);
1305 public void setDbProperties(Properties dbProperties) {
1306 getPoolProperties().setDbProperties(dbProperties);
1314 public void setDefaultReadOnly(Boolean defaultReadOnly) {
1315 getPoolProperties().setDefaultReadOnly(defaultReadOnly);
1323 public void setMaxAge(long maxAge) {
1324 getPoolProperties().setMaxAge(maxAge);
1332 public void setName(String name) {
1333 getPoolProperties().setName(name);
1340 public void setDataSource(Object ds) {
1341 getPoolProperties().setDataSource(ds);
1348 public Object getDataSource() {
1349 return getPoolProperties().getDataSource();
1357 public void setDataSourceJNDI(String jndiDS) {
1358 getPoolProperties().setDataSourceJNDI(jndiDS);
1365 public String getDataSourceJNDI() {
1366 return getPoolProperties().getDataSourceJNDI();
1373 public boolean isAlternateUsernameAllowed() {
1374 return getPoolProperties().isAlternateUsernameAllowed();
1381 public void setAlternateUsernameAllowed(boolean alternateUsernameAllowed) {
1382 getPoolProperties().setAlternateUsernameAllowed(alternateUsernameAllowed);
1389 public void setCommitOnReturn(boolean commitOnReturn) {
1390 getPoolProperties().setCommitOnReturn(commitOnReturn);
1397 public boolean getCommitOnReturn() {
1398 return getPoolProperties().getCommitOnReturn();
1405 public void setRollbackOnReturn(boolean rollbackOnReturn) {
1406 getPoolProperties().setRollbackOnReturn(rollbackOnReturn);
1413 public boolean getRollbackOnReturn() {
1414 return getPoolProperties().getRollbackOnReturn();
1421 public void setUseDisposableConnectionFacade(boolean useDisposableConnectionFacade) {
1422 getPoolProperties().setUseDisposableConnectionFacade(useDisposableConnectionFacade);
1429 public boolean getUseDisposableConnectionFacade() {
1430 return getPoolProperties().getUseDisposableConnectionFacade();
1437 public void setLogValidationErrors(boolean logValidationErrors) {
1438 getPoolProperties().setLogValidationErrors(logValidationErrors);
1445 public boolean getLogValidationErrors() {
1446 return getPoolProperties().getLogValidationErrors();
1453 public boolean getPropagateInterruptState() {
1454 return getPoolProperties().getPropagateInterruptState();
1461 public void setPropagateInterruptState(boolean propagateInterruptState) {
1462 getPoolProperties().setPropagateInterruptState(propagateInterruptState);
1469 public boolean isIgnoreExceptionOnPreLoad() {
1470 return getPoolProperties().isIgnoreExceptionOnPreLoad();
1477 public void setIgnoreExceptionOnPreLoad(boolean ignoreExceptionOnPreLoad) {
1478 getPoolProperties().setIgnoreExceptionOnPreLoad(ignoreExceptionOnPreLoad);
1481 public void purge() {
1483 createPool().purge();
1484 }catch (SQLException x) {
1485 log.error("Unable to purge pool.",x);
1489 public void purgeOnReturn() {
1491 createPool().purgeOnReturn();
1492 }catch (SQLException x) {
1493 log.error("Unable to purge pool.",x);