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=========================================================
21 /* Licensed to the Apache Software Foundation (ASF) under one or more
22 * contributor license agreements. See the NOTICE file distributed with
23 * this work for additional information regarding copyright ownership.
24 * The ASF licenses this file to You under the Apache License, Version 2.0
25 * (the "License"); you may not use this file except in compliance with
26 * the License. You may obtain a copy of the License at
28 * http://www.apache.org/licenses/LICENSE-2.0
30 * Unless required by applicable law or agreed to in writing, software
31 * distributed under the License is distributed on an "AS IS" BASIS,
32 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
33 * See the License for the specific language governing permissions and
34 * limitations under the License.
36 package org.apache.tomcat.jdbc.pool.jmx;
38 import java.util.Properties;
39 import java.util.concurrent.ConcurrentLinkedQueue;
40 import java.util.concurrent.atomic.AtomicInteger;
42 import javax.management.MBeanNotificationInfo;
43 import javax.management.Notification;
44 import javax.management.NotificationBroadcasterSupport;
45 import javax.management.NotificationListener;
47 import org.apache.juli.logging.Log;
48 import org.apache.juli.logging.LogFactory;
49 import org.apache.tomcat.jdbc.pool.PoolConfiguration;
50 import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorDefinition;
51 import org.apache.tomcat.jdbc.pool.PoolUtilities;
52 import org.apache.tomcat.jdbc.pool.Validator;
54 public class ConnectionPool extends NotificationBroadcasterSupport implements ConnectionPoolMBean {
58 private static final Log log = LogFactory.getLog(ConnectionPool.class);
63 protected org.apache.tomcat.jdbc.pool.ConnectionPool pool = null;
65 * sequence for JMX notifications
67 protected AtomicInteger sequence = new AtomicInteger(0);
70 * Listeners that are local and interested in our notifications, no need for JMX
72 protected ConcurrentLinkedQueue<NotificationListener> listeners =
73 new ConcurrentLinkedQueue<>();
75 public ConnectionPool(org.apache.tomcat.jdbc.pool.ConnectionPool pool) {
80 public org.apache.tomcat.jdbc.pool.ConnectionPool getPool() {
84 public PoolConfiguration getPoolProperties() {
85 return pool.getPoolProperties();
88 //=================================================================
90 //=================================================================
91 public static final String NOTIFY_INIT = "INIT FAILED";
92 public static final String NOTIFY_CONNECT = "CONNECTION FAILED";
93 public static final String NOTIFY_ABANDON = "CONNECTION ABANDONED";
94 public static final String SLOW_QUERY_NOTIFICATION = "SLOW QUERY";
95 public static final String FAILED_QUERY_NOTIFICATION = "FAILED QUERY";
96 public static final String SUSPECT_ABANDONED_NOTIFICATION = "SUSPECT CONNECTION ABANDONED";
97 public static final String POOL_EMPTY = "POOL EMPTY";
98 public static final String SUSPECT_RETURNED_NOTIFICATION = "SUSPECT CONNECTION RETURNED";
101 public MBeanNotificationInfo[] getNotificationInfo() {
102 MBeanNotificationInfo[] pres = super.getNotificationInfo();
103 MBeanNotificationInfo[] loc = getDefaultNotificationInfo();
104 MBeanNotificationInfo[] aug = new MBeanNotificationInfo[pres.length + loc.length];
105 if (pres.length>0) System.arraycopy(pres, 0, aug, 0, pres.length);
106 if (loc.length >0) System.arraycopy(loc, 0, aug, pres.length, loc.length);
110 public static MBeanNotificationInfo[] getDefaultNotificationInfo() {
111 String[] types = new String[] {NOTIFY_INIT, NOTIFY_CONNECT, NOTIFY_ABANDON, SLOW_QUERY_NOTIFICATION,
112 FAILED_QUERY_NOTIFICATION, SUSPECT_ABANDONED_NOTIFICATION, POOL_EMPTY, SUSPECT_RETURNED_NOTIFICATION};
113 String name = Notification.class.getName();
114 String description = "A connection pool error condition was met.";
115 MBeanNotificationInfo info = new MBeanNotificationInfo(types, name, description);
116 return new MBeanNotificationInfo[] {info};
120 * Return true if the notification was sent successfully, false otherwise.
121 * @param type The notification type
122 * @param message The message
123 * @return true if the notification succeeded
125 public boolean notify(final String type, String message) {
127 Notification n = new Notification(
130 sequence.incrementAndGet(),
131 System.currentTimeMillis(),
132 "["+type+"] "+message);
134 for (NotificationListener listener : listeners) {
135 listener.handleNotification(n,this);
138 }catch (Exception x) {
139 if (log.isDebugEnabled()) {
140 log.debug("Notify failed. Type="+type+"; Message="+message,x);
147 public void addListener(NotificationListener list) {
151 public boolean removeListener(NotificationListener list) {
152 return listeners.remove(list);
155 //=================================================================
157 //=================================================================
160 public int getSize() {
161 return pool.getSize();
165 public int getIdle() {
166 return pool.getIdle();
170 public int getActive() {
171 return pool.getActive();
175 public int getNumIdle() {
180 public int getNumActive() {
185 public int getWaitCount() {
186 return pool.getWaitCount();
190 public long getBorrowedCount() {
191 return pool.getBorrowedCount();
195 public long getReturnedCount() {
196 return pool.getReturnedCount();
200 public long getCreatedCount() {
201 return pool.getCreatedCount();
205 public long getReleasedCount() {
206 return pool.getReleasedCount();
210 public long getReconnectedCount() {
211 return pool.getReconnectedCount();
215 public long getRemoveAbandonedCount() {
216 return pool.getRemoveAbandonedCount();
220 public long getReleasedIdleCount() {
221 return pool.getReleasedIdleCount();
224 //=================================================================
226 //=================================================================
228 public void checkIdle() {
233 public void checkAbandoned() {
234 pool.checkAbandoned();
238 public void testIdle() {
243 public void resetStats() {
247 //=================================================================
249 //=================================================================
250 //=========================================================
251 // PROPERTIES / CONFIGURATION
252 //=========================================================
256 public String getConnectionProperties() {
257 return getPoolProperties().getConnectionProperties();
261 public Properties getDbProperties() {
262 return PoolUtilities.cloneWithoutPassword(getPoolProperties().getDbProperties());
266 public String getDefaultCatalog() {
267 return getPoolProperties().getDefaultCatalog();
271 public int getDefaultTransactionIsolation() {
272 return getPoolProperties().getDefaultTransactionIsolation();
276 public String getDriverClassName() {
277 return getPoolProperties().getDriverClassName();
282 public int getInitialSize() {
283 return getPoolProperties().getInitialSize();
287 public String getInitSQL() {
288 return getPoolProperties().getInitSQL();
292 public String getJdbcInterceptors() {
293 return getPoolProperties().getJdbcInterceptors();
297 public int getMaxActive() {
298 return getPoolProperties().getMaxActive();
302 public int getMaxIdle() {
303 return getPoolProperties().getMaxIdle();
307 public int getMaxWait() {
308 return getPoolProperties().getMaxWait();
312 public int getMinEvictableIdleTimeMillis() {
313 return getPoolProperties().getMinEvictableIdleTimeMillis();
317 public int getMinIdle() {
318 return getPoolProperties().getMinIdle();
322 public long getMaxAge() {
323 return getPoolProperties().getMaxAge();
327 public String getName() {
328 return this.getPoolName();
332 public int getNumTestsPerEvictionRun() {
333 return getPoolProperties().getNumTestsPerEvictionRun();
337 * @return DOES NOT RETURN THE PASSWORD, IT WOULD SHOW UP IN JMX
340 public String getPassword() {
341 return "Password not available as DataSource/JMX operation.";
345 public int getRemoveAbandonedTimeout() {
346 return getPoolProperties().getRemoveAbandonedTimeout();
351 public int getTimeBetweenEvictionRunsMillis() {
352 return getPoolProperties().getTimeBetweenEvictionRunsMillis();
356 public String getUrl() {
357 return getPoolProperties().getUrl();
361 public String getUsername() {
362 return getPoolProperties().getUsername();
366 public long getValidationInterval() {
367 return getPoolProperties().getValidationInterval();
371 public String getValidationQuery() {
372 return getPoolProperties().getValidationQuery();
376 public int getValidationQueryTimeout() {
377 return getPoolProperties().getValidationQueryTimeout();
385 public String getValidatorClassName() {
386 return getPoolProperties().getValidatorClassName();
394 public Validator getValidator() {
395 return getPoolProperties().getValidator();
399 public boolean isAccessToUnderlyingConnectionAllowed() {
400 return getPoolProperties().isAccessToUnderlyingConnectionAllowed();
404 public Boolean isDefaultAutoCommit() {
405 return getPoolProperties().isDefaultAutoCommit();
409 public Boolean isDefaultReadOnly() {
410 return getPoolProperties().isDefaultReadOnly();
414 public boolean isLogAbandoned() {
415 return getPoolProperties().isLogAbandoned();
419 public boolean isPoolSweeperEnabled() {
420 return getPoolProperties().isPoolSweeperEnabled();
424 public boolean isRemoveAbandoned() {
425 return getPoolProperties().isRemoveAbandoned();
429 public int getAbandonWhenPercentageFull() {
430 return getPoolProperties().getAbandonWhenPercentageFull();
434 public boolean isTestOnBorrow() {
435 return getPoolProperties().isTestOnBorrow();
439 public boolean isTestOnConnect() {
440 return getPoolProperties().isTestOnConnect();
444 public boolean isTestOnReturn() {
445 return getPoolProperties().isTestOnReturn();
449 public boolean isTestWhileIdle() {
450 return getPoolProperties().isTestWhileIdle();
455 public Boolean getDefaultAutoCommit() {
456 return getPoolProperties().getDefaultAutoCommit();
460 public Boolean getDefaultReadOnly() {
461 return getPoolProperties().getDefaultReadOnly();
465 public InterceptorDefinition[] getJdbcInterceptorsAsArray() {
466 return getPoolProperties().getJdbcInterceptorsAsArray();
470 public boolean getUseLock() {
471 return getPoolProperties().getUseLock();
475 public boolean isFairQueue() {
476 return getPoolProperties().isFairQueue();
480 public boolean isJmxEnabled() {
481 return getPoolProperties().isJmxEnabled();
485 public boolean isUseEquals() {
486 return getPoolProperties().isUseEquals();
490 public void setAbandonWhenPercentageFull(int percentage) {
491 getPoolProperties().setAbandonWhenPercentageFull(percentage);
495 public void setAccessToUnderlyingConnectionAllowed(boolean accessToUnderlyingConnectionAllowed) {
496 getPoolProperties().setAccessToUnderlyingConnectionAllowed(accessToUnderlyingConnectionAllowed);
500 public void setDbProperties(Properties dbProperties) {
501 getPoolProperties().setDbProperties(dbProperties);
505 public void setDefaultReadOnly(Boolean defaultReadOnly) {
506 getPoolProperties().setDefaultReadOnly(defaultReadOnly);
510 public void setMaxAge(long maxAge) {
511 getPoolProperties().setMaxAge(maxAge);
515 public void setName(String name) {
516 getPoolProperties().setName(name);
520 public String getPoolName() {
521 return getPoolProperties().getName();
526 public void setConnectionProperties(String connectionProperties) {
527 getPoolProperties().setConnectionProperties(connectionProperties);
532 public void setDefaultAutoCommit(Boolean defaultAutoCommit) {
533 getPoolProperties().setDefaultAutoCommit(defaultAutoCommit);
537 public void setDefaultCatalog(String defaultCatalog) {
538 getPoolProperties().setDefaultCatalog(defaultCatalog);
542 public void setDefaultTransactionIsolation(int defaultTransactionIsolation) {
543 getPoolProperties().setDefaultTransactionIsolation(defaultTransactionIsolation);
547 public void setDriverClassName(String driverClassName) {
548 getPoolProperties().setDriverClassName(driverClassName);
553 public void setFairQueue(boolean fairQueue) {
554 // noop - this pool is already running
555 throw new UnsupportedOperationException();
560 public void setInitialSize(int initialSize) {
561 // noop - this pool is already running
562 throw new UnsupportedOperationException();
568 public void setInitSQL(String initSQL) {
569 getPoolProperties().setInitSQL(initSQL);
575 public void setJdbcInterceptors(String jdbcInterceptors) {
576 // noop - this pool is already running
577 throw new UnsupportedOperationException();
582 public void setJmxEnabled(boolean jmxEnabled) {
583 // noop - this pool is already running and obviously jmx enabled
584 throw new UnsupportedOperationException();
589 public void setLogAbandoned(boolean logAbandoned) {
590 getPoolProperties().setLogAbandoned(logAbandoned);
595 public void setMaxActive(int maxActive) {
596 getPoolProperties().setMaxActive(maxActive);
597 //make sure the pool is properly configured
598 pool.checkPoolConfiguration(getPoolProperties());
603 public void setMaxIdle(int maxIdle) {
604 getPoolProperties().setMaxIdle(maxIdle);
605 //make sure the pool is properly configured
606 pool.checkPoolConfiguration(getPoolProperties());
612 public void setMaxWait(int maxWait) {
613 getPoolProperties().setMaxWait(maxWait);
618 public void setMinEvictableIdleTimeMillis(int minEvictableIdleTimeMillis) {
619 boolean wasEnabled = getPoolProperties().isPoolSweeperEnabled();
620 getPoolProperties().setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
621 boolean shouldBeEnabled = getPoolProperties().isPoolSweeperEnabled();
622 //make sure pool cleaner starts/stops when it should
623 if (!wasEnabled && shouldBeEnabled) pool.initializePoolCleaner(getPoolProperties());
624 else if (wasEnabled && !shouldBeEnabled) pool.terminatePoolCleaner();
629 public void setMinIdle(int minIdle) {
630 getPoolProperties().setMinIdle(minIdle);
631 //make sure the pool is properly configured
632 pool.checkPoolConfiguration(getPoolProperties());
637 public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) {
638 getPoolProperties().setNumTestsPerEvictionRun(numTestsPerEvictionRun);
643 public void setPassword(String password) {
644 getPoolProperties().setPassword(password);
649 public void setRemoveAbandoned(boolean removeAbandoned) {
650 boolean wasEnabled = getPoolProperties().isPoolSweeperEnabled();
651 getPoolProperties().setRemoveAbandoned(removeAbandoned);
652 boolean shouldBeEnabled = getPoolProperties().isPoolSweeperEnabled();
653 //make sure pool cleaner starts/stops when it should
654 if (!wasEnabled && shouldBeEnabled) pool.initializePoolCleaner(getPoolProperties());
655 else if (wasEnabled && !shouldBeEnabled) pool.terminatePoolCleaner();
660 public void setRemoveAbandonedTimeout(int removeAbandonedTimeout) {
661 boolean wasEnabled = getPoolProperties().isPoolSweeperEnabled();
662 getPoolProperties().setRemoveAbandonedTimeout(removeAbandonedTimeout);
663 boolean shouldBeEnabled = getPoolProperties().isPoolSweeperEnabled();
664 //make sure pool cleaner starts/stops when it should
665 if (!wasEnabled && shouldBeEnabled) pool.initializePoolCleaner(getPoolProperties());
666 else if (wasEnabled && !shouldBeEnabled) pool.terminatePoolCleaner();
671 public void setTestOnBorrow(boolean testOnBorrow) {
672 getPoolProperties().setTestOnBorrow(testOnBorrow);
677 public void setTestOnConnect(boolean testOnConnect) {
678 getPoolProperties().setTestOnConnect(testOnConnect);
683 public void setTestOnReturn(boolean testOnReturn) {
684 getPoolProperties().setTestOnReturn(testOnReturn);
689 public void setTestWhileIdle(boolean testWhileIdle) {
690 boolean wasEnabled = getPoolProperties().isPoolSweeperEnabled();
691 getPoolProperties().setTestWhileIdle(testWhileIdle);
692 boolean shouldBeEnabled = getPoolProperties().isPoolSweeperEnabled();
693 //make sure pool cleaner starts/stops when it should
694 if (!wasEnabled && shouldBeEnabled) pool.initializePoolCleaner(getPoolProperties());
695 else if (wasEnabled && !shouldBeEnabled) pool.terminatePoolCleaner();
700 public void setTimeBetweenEvictionRunsMillis(int timeBetweenEvictionRunsMillis) {
701 boolean wasEnabled = getPoolProperties().isPoolSweeperEnabled();
702 getPoolProperties().setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
703 boolean shouldBeEnabled = getPoolProperties().isPoolSweeperEnabled();
704 //make sure pool cleaner starts/stops when it should
705 if (!wasEnabled && shouldBeEnabled) {
706 pool.initializePoolCleaner(getPoolProperties());
707 } else if (wasEnabled) {
708 pool.terminatePoolCleaner();
709 if (shouldBeEnabled) {
710 pool.initializePoolCleaner(getPoolProperties());
717 public void setUrl(String url) {
718 getPoolProperties().setUrl(url);
723 public void setUseEquals(boolean useEquals) {
724 getPoolProperties().setUseEquals(useEquals);
729 public void setUseLock(boolean useLock) {
730 getPoolProperties().setUseLock(useLock);
735 public void setUsername(String username) {
736 getPoolProperties().setUsername(username);
741 public void setValidationInterval(long validationInterval) {
742 getPoolProperties().setValidationInterval(validationInterval);
747 public void setValidationQuery(String validationQuery) {
748 getPoolProperties().setValidationQuery(validationQuery);
752 public void setValidationQueryTimeout(int validationQueryTimeout) {
753 getPoolProperties().setValidationQueryTimeout(validationQueryTimeout);
761 public void setValidatorClassName(String className) {
762 getPoolProperties().setValidatorClassName(className);
770 public int getSuspectTimeout() {
771 return getPoolProperties().getSuspectTimeout();
779 public void setSuspectTimeout(int seconds) {
780 getPoolProperties().setSuspectTimeout(seconds);
787 public void setDataSource(Object ds) {
788 getPoolProperties().setDataSource(ds);
795 public Object getDataSource() {
796 return getPoolProperties().getDataSource();
804 public void setDataSourceJNDI(String jndiDS) {
805 getPoolProperties().setDataSourceJNDI(jndiDS);
812 public String getDataSourceJNDI() {
813 return getPoolProperties().getDataSourceJNDI();
820 public boolean isAlternateUsernameAllowed() {
821 return getPoolProperties().isAlternateUsernameAllowed();
828 public void setAlternateUsernameAllowed(boolean alternateUsernameAllowed) {
829 getPoolProperties().setAlternateUsernameAllowed(alternateUsernameAllowed);
836 public void setValidator(Validator validator) {
837 getPoolProperties().setValidator(validator);
844 public void setCommitOnReturn(boolean commitOnReturn) {
845 getPoolProperties().setCommitOnReturn(commitOnReturn);
852 public boolean getCommitOnReturn() {
853 return getPoolProperties().getCommitOnReturn();
860 public void setRollbackOnReturn(boolean rollbackOnReturn) {
861 getPoolProperties().setRollbackOnReturn(rollbackOnReturn);
868 public boolean getRollbackOnReturn() {
869 return getPoolProperties().getRollbackOnReturn();
876 public void setUseDisposableConnectionFacade(boolean useDisposableConnectionFacade) {
877 getPoolProperties().setUseDisposableConnectionFacade(useDisposableConnectionFacade);
884 public boolean getUseDisposableConnectionFacade() {
885 return getPoolProperties().getUseDisposableConnectionFacade();
892 public void setLogValidationErrors(boolean logValidationErrors) {
893 getPoolProperties().setLogValidationErrors(logValidationErrors);
900 public boolean getLogValidationErrors() {
901 return getPoolProperties().getLogValidationErrors();
909 public boolean getPropagateInterruptState() {
910 return getPoolProperties().getPropagateInterruptState();
917 public void setPropagateInterruptState(boolean propagateInterruptState) {
918 getPoolProperties().setPropagateInterruptState(propagateInterruptState);
925 public boolean isIgnoreExceptionOnPreLoad() {
926 return getPoolProperties().isIgnoreExceptionOnPreLoad();
933 public void setIgnoreExceptionOnPreLoad(boolean ignoreExceptionOnPreLoad) {
934 // noop - this pool is already running
935 throw new UnsupportedOperationException();
942 public void purge() {
951 public void purgeOnReturn() {
952 pool.purgeOnReturn();