Author: markt Date: Mon Dec 4 14:44:22 2017 New Revision: 1817096 URL: http://svn.apache.org/viewvc?rev=1817096&view=rev Log: Align packaged renamed Pool2 with original. I ended up adding the useless (in the context of DBCP) SecurityManager based CallStack implementation because excluding was complicating the merge. This aligns the Commons Pool fork to the 2.4.3 release.
Added: tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/CallStackUtils.java (with props) tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/NoOpCallStack.java (with props) tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/SecurityManagerCallStack.java (with props) Modified: tomcat/trunk/MERGE.txt tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/BaseKeyedPooledObjectFactory.java tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/BasePooledObjectFactory.java tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/KeyedObjectPool.java tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/ObjectPool.java tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/PoolUtils.java tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/PooledObject.java tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/AbandonedConfig.java tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/BaseObjectPoolConfig.java tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/CallStack.java tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/DefaultPooledObject.java tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/DefaultPooledObjectInfoMBean.java tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/EvictionTimer.java tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPool.java tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPool.java tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/LinkedBlockingDeque.java tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/SoftReferenceObjectPool.java tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/ThrowableCallStack.java tomcat/trunk/webapps/docs/changelog.xml Modified: tomcat/trunk/MERGE.txt URL: http://svn.apache.org/viewvc/tomcat/trunk/MERGE.txt?rev=1817096&r1=1817095&r2=1817096&view=diff ============================================================================== --- tomcat/trunk/MERGE.txt (original) +++ tomcat/trunk/MERGE.txt Mon Dec 4 14:44:22 2017 @@ -35,13 +35,15 @@ BCEL org.apache.tomcat.util.bcel is copied from: /commons/proper/bcel/trunk/src/main/java/org/apache/bcel -DBCP +DBCP (inc. Pool2) org.apache.tomcat.dbcp.dbcp2 is copied from: /commons/proper/dbcp/trunk/src/main/java/org/apache/commons/dbcp2 and /commons/proper/dbcp/trunk/src/main/resources/org/apache/commons/dbcp2 -org.apache.tomcat.dbcp.pool2 is copied from: -/commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2 + +Pool2 used to be hosted in svn. All changes up to the point where Pool2 was +migrated to git have been merged. + FileUpload This used to be hosted in svn. All changes up to the point where FileUpload was @@ -70,3 +72,9 @@ The SHA1 ID for the most recent commit t Note: Tomcat's copy of fileupload also includes classes copied manually (rather than svn copied) from Commons IO. + +Pool2 +Sub-tree +src/main/java/org/apache/commons/pool2 +The SHA1 ID for the most recent commit to be merged to Tomcat is: +191a391166a8565718ef685531afa3fa44afd69c Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/BaseKeyedPooledObjectFactory.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/BaseKeyedPooledObjectFactory.java?rev=1817096&r1=1817095&r2=1817096&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/BaseKeyedPooledObjectFactory.java (original) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/BaseKeyedPooledObjectFactory.java Mon Dec 4 14:44:22 2017 @@ -66,11 +66,12 @@ public abstract class BaseKeyedPooledObj * The default implementation is a no-op. * * @param key the key used when selecting the instance - * @param p a {@code PooledObject} wrapping the the instance to be destroyed + * @param p a {@code PooledObject} wrapping the instance to be destroyed */ @Override public void destroyObject(final K key, final PooledObject<V> p) throws Exception { + // The default implementation is a no-op. } /** @@ -79,7 +80,7 @@ public abstract class BaseKeyedPooledObj * The default implementation always returns {@code true}. * * @param key the key used when selecting the object - * @param p a {@code PooledObject} wrapping the the instance to be validated + * @param p a {@code PooledObject} wrapping the instance to be validated * @return always <code>true</code> in the default implementation */ @Override @@ -93,11 +94,12 @@ public abstract class BaseKeyedPooledObj * The default implementation is a no-op. * * @param key the key used when selecting the object - * @param p a {@code PooledObject} wrapping the the instance to be activated + * @param p a {@code PooledObject} wrapping the instance to be activated */ @Override public void activateObject(final K key, final PooledObject<V> p) throws Exception { + // The default implementation is a no-op. } /** @@ -106,10 +108,11 @@ public abstract class BaseKeyedPooledObj * The default implementation is a no-op. * * @param key the key used when selecting the object - * @param p a {@code PooledObject} wrapping the the instance to be passivated + * @param p a {@code PooledObject} wrapping the instance to be passivated */ @Override public void passivateObject(final K key, final PooledObject<V> p) throws Exception { + // The default implementation is a no-op. } } Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/BasePooledObjectFactory.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/BasePooledObjectFactory.java?rev=1817096&r1=1817095&r2=1817096&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/BasePooledObjectFactory.java (original) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/BasePooledObjectFactory.java Mon Dec 4 14:44:22 2017 @@ -66,6 +66,7 @@ public abstract class BasePooledObjectFa @Override public void destroyObject(final PooledObject<T> p) throws Exception { + // The default implementation is a no-op. } /** @@ -87,6 +88,7 @@ public abstract class BasePooledObjectFa */ @Override public void activateObject(final PooledObject<T> p) throws Exception { + // The default implementation is a no-op. } /** @@ -97,5 +99,6 @@ public abstract class BasePooledObjectFa @Override public void passivateObject(final PooledObject<T> p) throws Exception { + // The default implementation is a no-op. } } Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/KeyedObjectPool.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/KeyedObjectPool.java?rev=1817096&r1=1817095&r2=1817096&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/KeyedObjectPool.java (original) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/KeyedObjectPool.java Mon Dec 4 14:44:22 2017 @@ -16,6 +16,7 @@ */ package org.apache.tomcat.dbcp.pool2; +import java.io.Closeable; import java.util.NoSuchElementException; /** @@ -60,7 +61,7 @@ import java.util.NoSuchElementException; * * @since 2.0 */ -public interface KeyedObjectPool<K,V> { +public interface KeyedObjectPool<K,V> extends Closeable { /** * Obtains an instance from this pool for the specified <code>key</code>. * <p> @@ -224,5 +225,6 @@ public interface KeyedObjectPool<K,V> { * <p> * Implementations should silently fail if not all resources can be freed. */ + @Override void close(); } Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/ObjectPool.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/ObjectPool.java?rev=1817096&r1=1817095&r2=1817096&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/ObjectPool.java (original) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/ObjectPool.java Mon Dec 4 14:44:22 2017 @@ -16,6 +16,7 @@ */ package org.apache.tomcat.dbcp.pool2; +import java.io.Closeable; import java.util.NoSuchElementException; /** @@ -54,7 +55,7 @@ import java.util.NoSuchElementException; * * @since 2.0 */ -public interface ObjectPool<T> { +public interface ObjectPool<T> extends Closeable { /** * Obtains an instance from this pool. * <p> @@ -172,5 +173,6 @@ public interface ObjectPool<T> { * <p> * Implementations should silently fail if not all resources can be freed. */ + @Override void close(); } Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/PoolUtils.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/PoolUtils.java?rev=1817096&r1=1817095&r2=1817096&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/PoolUtils.java (original) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/PoolUtils.java Mon Dec 4 14:44:22 2017 @@ -19,6 +19,7 @@ package org.apache.tomcat.dbcp.pool2; import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.Iterator; import java.util.Map; import java.util.NoSuchElementException; import java.util.Timer; @@ -190,7 +191,9 @@ public final class PoolUtils { throw new IllegalArgumentException("keys must not be null."); } final Map<K, TimerTask> tasks = new HashMap<>(keys.size()); - for (K key : keys) { + final Iterator<K> iter = keys.iterator(); + while (iter.hasNext()) { + final K key = iter.next(); final TimerTask task = checkMinIdle(keyedPool, key, minIdle, period); tasks.put(key, task); } @@ -280,8 +283,9 @@ public final class PoolUtils { if (keys == null) { throw new IllegalArgumentException("keys must not be null."); } - for (K key : keys) { - prefill(keyedPool, key, count); + final Iterator<K> iter = keys.iterator(); + while (iter.hasNext()) { + prefill(keyedPool, iter.next(), count); } } @@ -558,6 +562,8 @@ public final class PoolUtils { * Timer task that adds objects to the pool until the number of idle * instances reaches the configured minIdle. Note that this is not the same * as the pool's minIdle setting. + * + * @param <T> type of objects in the pool */ private static final class ObjectPoolMinIdleTimerTask<T> extends TimerTask { @@ -627,6 +633,9 @@ public final class PoolUtils { * Timer task that adds objects to the pool until the number of idle * instances for the given key reaches the configured minIdle. Note that * this is not the same as the pool's minIdle setting. + * + * @param <K> object pool key type + * @param <V> object pool value type */ private static final class KeyedObjectPoolMinIdleTimerTask<K, V> extends TimerTask { @@ -711,6 +720,8 @@ public final class PoolUtils { * another layer of synchronization will cause liveliness issues or a * deadlock. * </p> + * + * @param <T> type of objects in the pool */ private static final class SynchronizedObjectPool<T> implements ObjectPool<T> { @@ -884,6 +895,9 @@ public final class PoolUtils { * another layer of synchronization will cause liveliness issues or a * deadlock. * </p> + * + * @param <K> object pool key type + * @param <V> object pool value type */ private static final class SynchronizedKeyedObjectPool<K, V> implements KeyedObjectPool<K, V> { @@ -1099,6 +1113,8 @@ public final class PoolUtils { * provide proper synchronization such as the pools provided in the Commons * Pool library. * </p> + * + * @param <T> pooled object factory type */ private static final class SynchronizedPooledObjectFactory<T> implements PooledObjectFactory<T> { @@ -1212,6 +1228,9 @@ public final class PoolUtils { * provide proper synchronization such as the pools provided in the Commons * Pool library. * </p> + * + * @param <K> pooled object factory key type + * @param <V> pooled object factory key value */ private static final class SynchronizedKeyedPooledObjectFactory<K, V> implements KeyedPooledObjectFactory<K, V> { @@ -1395,6 +1414,8 @@ public final class PoolUtils { * Decorates an object pool, adding "eroding" behavior. Based on the * configured {@link #factor erosion factor}, objects returning to the pool * may be invalidated instead of being added to idle capacity. + * + * @param <T> type of objects in the pool */ private static class ErodingObjectPool<T> implements ObjectPool<T> { /** Underlying object pool */ @@ -1536,6 +1557,9 @@ public final class PoolUtils { * Decorates a keyed object pool, adding "eroding" behavior. Based on the * configured erosion factor, objects returning to the pool * may be invalidated instead of being added to idle capacity. + * + * @param <K> object pool key type + * @param <V> object pool value type */ private static class ErodingKeyedObjectPool<K, V> implements KeyedObjectPool<K, V> { @@ -1746,6 +1770,9 @@ public final class PoolUtils { * Extends ErodingKeyedObjectPool to allow erosion to take place on a * per-key basis. Timing of erosion events is tracked separately for * separate keyed pools. + * + * @param <K> object pool key type + * @param <V> object pool value type */ private static final class ErodingPerKeyKeyedObjectPool<K, V> extends ErodingKeyedObjectPool<K, V> { Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/PooledObject.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/PooledObject.java?rev=1817096&r1=1817095&r2=1817096&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/PooledObject.java (original) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/PooledObject.java Mon Dec 4 14:44:22 2017 @@ -48,7 +48,7 @@ public interface PooledObject<T> extends long getCreateTime(); /** - * Obtain the time in milliseconds that this object last spent in the the + * Obtain the time in milliseconds that this object last spent in the * active state (it may still be active in which case subsequent calls will * return an increased value). * @@ -57,7 +57,7 @@ public interface PooledObject<T> extends long getActiveTimeMillis(); /** - * Obtain the time in milliseconds that this object last spend in the the + * Obtain the time in milliseconds that this object last spend in the * idle state (it may still be idle in which case subsequent calls will * return an increased value). * @@ -167,6 +167,18 @@ public interface PooledObject<T> extends */ void setLogAbandoned(boolean logAbandoned); +// TODO: uncomment in 3.0 (API compatibility) +// /** +// * Configures the stack trace generation strategy based on whether or not fully +// * detailed stack traces are required. When set to false, abandoned logs may +// * only include caller class information rather than method names, line numbers, +// * and other normal metadata available in a full stack trace. +// * +// * @param requireFullStackTrace the new configuration setting for abandoned object +// * logging +// */ +// void setRequireFullStackTrace(boolean requireFullStackTrace); + /** * Record the current stack trace as the last time the object was used. */ Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/AbandonedConfig.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/AbandonedConfig.java?rev=1817096&r1=1817095&r2=1817096&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/AbandonedConfig.java (original) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/AbandonedConfig.java Mon Dec 4 14:44:22 2017 @@ -168,6 +168,43 @@ public class AbandonedConfig { } /** + * Determines whether or not to log full stack traces when logAbandoned is true. + * If disabled, then a faster method for logging stack traces with only class data + * may be used if possible. + * + * @since 2.5 + */ + private boolean requireFullStackTrace = true; + + /** + * Indicates if full stack traces are required when {@link #getLogAbandoned() logAbandoned} + * is true. Defaults to true. Logging of abandoned objects requiring a full stack trace will + * generate an entire stack trace to generate for every object created. If this is disabled, + * a faster but less informative stack walking mechanism may be used if available. + * + * @return true if full stack traces are required for logging abandoned connections, or false + * if abbreviated stack traces are acceptable + * @see CallStack + * @since 2.5 + */ + public boolean getRequireFullStackTrace() { + return requireFullStackTrace; + } + + /** + * Sets the flag to require full stack traces for logging abandoned connections when enabled. + * + * @param requireFullStackTrace indicates whether or not full stack traces are required in + * abandoned connection logs + * @see CallStack + * @see #getRequireFullStackTrace() + * @since 2.5 + */ + public void setRequireFullStackTrace(boolean requireFullStackTrace) { + this.requireFullStackTrace = requireFullStackTrace; + } + + /** * PrintWriter to use to log information on abandoned objects. * Use of default system encoding is deliberate. */ Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/BaseObjectPoolConfig.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/BaseObjectPoolConfig.java?rev=1817096&r1=1817095&r2=1817096&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/BaseObjectPoolConfig.java (original) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/BaseObjectPoolConfig.java Mon Dec 4 14:44:22 2017 @@ -170,7 +170,7 @@ public abstract class BaseObjectPoolConf private long maxWaitMillis = DEFAULT_MAX_WAIT_MILLIS; private long minEvictableIdleTimeMillis = - DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS; + DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS; private long evictorShutdownTimeoutMillis = DEFAULT_EVICTOR_SHUTDOWN_TIMEOUT_MILLIS; @@ -179,7 +179,7 @@ public abstract class BaseObjectPoolConf DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS; private int numTestsPerEvictionRun = - DEFAULT_NUM_TESTS_PER_EVICTION_RUN; + DEFAULT_NUM_TESTS_PER_EVICTION_RUN; private String evictionPolicyClassName = DEFAULT_EVICTION_POLICY_CLASS_NAME; @@ -192,7 +192,7 @@ public abstract class BaseObjectPoolConf private boolean testWhileIdle = DEFAULT_TEST_WHILE_IDLE; private long timeBetweenEvictionRunsMillis = - DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS; + DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS; private boolean blockWhenExhausted = DEFAULT_BLOCK_WHEN_EXHAUSTED; Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/CallStack.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/CallStack.java?rev=1817096&r1=1817095&r2=1817096&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/CallStack.java (original) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/CallStack.java Mon Dec 4 14:44:22 2017 @@ -21,7 +21,7 @@ import java.io.PrintWriter; /** * Strategy for obtaining and printing the current call stack. This is primarily useful for * {@linkplain UsageTracking usage tracking} so that different JVMs and configurations can use more efficient strategies - * for obtaining the current call stack. + * for obtaining the current call stack depending on metadata needs. * * @see CallStackUtils * @since 2.4.3 @@ -32,7 +32,7 @@ public interface CallStack { * Prints the current stack trace if available to a PrintWriter. The format is undefined and is primarily useful * for debugging issues with {@link PooledObject} usage in user code. * - * @param writer a PrintWriter to write the curren stack trace to if available + * @param writer a PrintWriter to write the current stack trace to if available * @return true if a stack trace was available to print or false if nothing was printed */ boolean printStackTrace(final PrintWriter writer); Added: tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/CallStackUtils.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/CallStackUtils.java?rev=1817096&view=auto ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/CallStackUtils.java (added) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/CallStackUtils.java Mon Dec 4 14:44:22 2017 @@ -0,0 +1,89 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tomcat.dbcp.pool2.impl; + +import java.security.AccessControlException; + +/** + * Utility methods for {@link CallStack}. + * + * @since 2.4.3 + */ +public final class CallStackUtils { + + private static final boolean CAN_CREATE_SECURITY_MANAGER; + + static { + CAN_CREATE_SECURITY_MANAGER = canCreateSecurityManager(); + } + + /** + * @return {@code true} if it is able to create a security manager in the current environment, {@code false} + * otherwise. + */ + private static boolean canCreateSecurityManager() { + final SecurityManager manager = System.getSecurityManager(); + if (manager == null) { + return true; + } + try { + manager.checkPermission(new RuntimePermission("createSecurityManager")); + return true; + } catch (final AccessControlException ignored) { + return false; + } + } + + /** + * Constructs a new {@link CallStack} using the fastest allowed strategy. + * + * @param messageFormat message (or format) to print first in stack traces + * @param useTimestamp if true, interpret message as a SimpleDateFormat and print the created timestamp; otherwise, + * print message format literally + * @return a new CallStack + * @deprecated use {@link #newCallStack(String, boolean, boolean)} + */ + @Deprecated + public static CallStack newCallStack(final String messageFormat, final boolean useTimestamp) { + return newCallStack(messageFormat, useTimestamp, false); + } + + /** + * Constructs a new {@link CallStack} using the fasted allowed strategy. + * + * @param messageFormat message (or format) to print first in stack traces + * @param useTimestamp if true, interpret message as a SimpleDateFormat and print the created timestamp; + * otherwise, print message format literally + * @param requireFullStackTrace if true, forces the use of a stack walking mechanism that includes full stack trace + * information; otherwise, uses a faster implementation if possible + * @return a new CallStack + * @since 2.5 + */ + public static CallStack newCallStack(final String messageFormat, + final boolean useTimestamp, + final boolean requireFullStackTrace) { + return CAN_CREATE_SECURITY_MANAGER && !requireFullStackTrace + ? new SecurityManagerCallStack(messageFormat, useTimestamp) + : new ThrowableCallStack(messageFormat, useTimestamp); + } + + /** + * Hidden constructor. + */ + private CallStackUtils() { + } +} Propchange: tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/CallStackUtils.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/DefaultPooledObject.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/DefaultPooledObject.java?rev=1817096&r1=1817095&r2=1817096&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/DefaultPooledObject.java (original) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/DefaultPooledObject.java Mon Dec 4 14:44:22 2017 @@ -42,10 +42,8 @@ public class DefaultPooledObject<T> impl private volatile long lastUseTime = createTime; private volatile long lastReturnTime = createTime; private volatile boolean logAbandoned = false; - private final CallStack borrowedBy = new ThrowableCallStack("'Pooled object created' " + - "yyyy-MM-dd HH:mm:ss Z 'by the following code has not been returned to the pool:'", true); - private final CallStack usedBy = new ThrowableCallStack("The last code to use this object was:", - false); + private volatile CallStack borrowedBy = NoOpCallStack.INSTANCE; + private volatile CallStack usedBy = NoOpCallStack.INSTANCE; private volatile long borrowedCount = 0; /** @@ -276,4 +274,24 @@ public class DefaultPooledObject<T> impl this.logAbandoned = logAbandoned; } - } + /** + * Configures the stack trace generation strategy based on whether or not fully + * detailed stack traces are required. When set to false, abandoned logs may + * only include caller class information rather than method names, line numbers, + * and other normal metadata available in a full stack trace. + * + * @param requireFullStackTrace the new configuration setting for abandoned object + * logging + * @since 2.5 + */ + // TODO: uncomment below in 3.0 + // @Override + public void setRequireFullStackTrace(final boolean requireFullStackTrace) { + borrowedBy = CallStackUtils.newCallStack("'Pooled object created' " + + "yyyy-MM-dd HH:mm:ss Z 'by the following code has not been returned to the pool:'", + true, requireFullStackTrace); + usedBy = CallStackUtils.newCallStack("The last code to use this object was:", + false, requireFullStackTrace); + } + +} Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/DefaultPooledObjectInfoMBean.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/DefaultPooledObjectInfoMBean.java?rev=1817096&r1=1817095&r2=1817096&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/DefaultPooledObjectInfoMBean.java (original) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/DefaultPooledObjectInfoMBean.java Mon Dec 4 14:44:22 2017 @@ -41,7 +41,7 @@ public interface DefaultPooledObjectInfo /** * Obtain the time that pooled object was created. * - * @return The creation time for the pooled object formated as + * @return The creation time for the pooled object formatted as * <code>yyyy-MM-dd HH:mm:ss Z</code> */ String getCreateTimeFormatted(); Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/EvictionTimer.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/EvictionTimer.java?rev=1817096&r1=1817095&r2=1817096&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/EvictionTimer.java (original) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/EvictionTimer.java Mon Dec 4 14:44:22 2017 @@ -27,7 +27,7 @@ import java.util.concurrent.TimeUnit; * Provides a shared idle object eviction timer for all pools. This class is * currently implemented using {@link ScheduledThreadPoolExecutor}. This * implementation may change in any future release. This class keeps track of - * how many pools are using it. If no pools are using the timer, it is canceled. + * how many pools are using it. If no pools are using the timer, it is cancelled. * This prevents a thread being left running which, in application server * environments, can lead to memory leads and/or prevent applications from * shutting down or reloading cleanly. @@ -76,10 +76,10 @@ class EvictionTimer { static synchronized void schedule(final Runnable task, final long delay, final long period) { if (null == executor) { executor = new ScheduledThreadPoolExecutor(1, new EvictorThreadFactory()); - } + } usageCount++; executor.scheduleWithFixedDelay(task, delay, period, TimeUnit.MILLISECONDS); - } + } /** * Remove the specified eviction task from the timer. @@ -90,22 +90,25 @@ class EvictionTimer { * terminate? * @param unit The units for the specified timeout */ - static synchronized void cancel(final TimerTask task, long timeout, TimeUnit unit) { + static synchronized void cancel(final TimerTask task, final long timeout, final TimeUnit unit) { task.cancel(); usageCount--; if (usageCount == 0) { executor.shutdown(); try { executor.awaitTermination(timeout, unit); - } catch (InterruptedException e) { + } catch (final InterruptedException e) { // Swallow // Significant API changes would be required to propagate this - } + } executor.setCorePoolSize(0); executor = null; - } + } } + /** + * Thread factory that creates a thread, with the context classloader from this class. + */ private static class EvictorThreadFactory implements ThreadFactory { @Override @@ -113,14 +116,14 @@ class EvictionTimer { final Thread t = new Thread(null, r, "commons-pool-evictor-thread"); AccessController.doPrivileged(new PrivilegedAction<Void>() { - @Override - public Void run() { + @Override + public Void run() { t.setContextClassLoader(EvictorThreadFactory.class.getClassLoader()); - return null; - } + return null; + } }); return t; } } - } +} Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPool.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPool.java?rev=1817096&r1=1817095&r2=1817096&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPool.java (original) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/GenericKeyedObjectPool.java Mon Dec 4 14:44:22 2017 @@ -51,6 +51,10 @@ import org.apache.tomcat.dbcp.pool2.Pool * provided to one of these methods, a sub-new pool is created under the given * key to be managed by the containing <code>GenericKeyedObjectPool.</code> * <p> + * Note that the current implementation uses a ConcurrentHashMap which uses + * equals() to compare keys. + * This means that distinct instance keys must be distinguishable using equals. + * <p> * Optionally, one may configure the pool to examine and possibly evict objects * as they sit idle in the pool and to ensure that a minimum number of idle * objects is maintained for each key. This is performed by an "idle object @@ -144,7 +148,7 @@ public class GenericKeyedObjectPool<K,T> * If maxIdlePerKey is set too low on heavily loaded systems it is possible * you will see objects being destroyed and almost immediately new objects * being created. This is a result of the active threads momentarily - * returning objects faster than they are requesting them them, causing the + * returning objects faster than they are requesting them, causing the * number of idle objects to rise above maxIdlePerKey. The best value for * maxIdlePerKey for heavily loaded system will vary but the default is a * good starting point. @@ -164,7 +168,7 @@ public class GenericKeyedObjectPool<K,T> * If maxIdlePerKey is set too low on heavily loaded systems it is possible * you will see objects being destroyed and almost immediately new objects * being created. This is a result of the active threads momentarily - * returning objects faster than they are requesting them them, causing the + * returning objects faster than they are requesting them, causing the * number of idle objects to rise above maxIdlePerKey. The best value for * maxIdlePerKey for heavily loaded system will vary but the default is a * good starting point. @@ -522,7 +526,7 @@ public class GenericKeyedObjectPool<K,T> final int maxIdle = getMaxIdlePerKey(); final LinkedBlockingDeque<PooledObject<T>> idleObjects = - objectDeque.getIdleObjects(); + objectDeque.getIdleObjects(); if (isClosed() || maxIdle > -1 && maxIdle <= idleObjects.size()) { try { @@ -608,8 +612,10 @@ public class GenericKeyedObjectPool<K,T> */ @Override public void clear() { - for (K k : poolMap.keySet()) { - clear(k); + final Iterator<K> iter = poolMap.keySet().iterator(); + + while (iter.hasNext()) { + clear(iter.next()); } } @@ -715,8 +721,9 @@ public class GenericKeyedObjectPool<K,T> jmxUnregister(); // Release any threads that were waiting for an object - for (ObjectDeque<T> deque : poolMap.values()) { - deque.getIdleObjects().interuptTakeWaiters(); + final Iterator<ObjectDeque<T>> iter = poolMap.values().iterator(); + while (iter.hasNext()) { + iter.next().getIdleObjects().interuptTakeWaiters(); } // This clear cleans up the keys now any waiting threads have been // interrupted @@ -734,7 +741,7 @@ public class GenericKeyedObjectPool<K,T> // build sorted map of idle objects final Map<PooledObject<T>, K> map = new TreeMap<>(); - for (Map.Entry<K, ObjectDeque<T>> entry : poolMap.entrySet()) { + for (final Map.Entry<K, ObjectDeque<T>> entry : poolMap.entrySet()) { final K k = entry.getKey(); final ObjectDeque<T> deque = entry.getValue(); // Protect against possible NPE if key has been removed in another @@ -754,7 +761,7 @@ public class GenericKeyedObjectPool<K,T> // for zero int itemsToRemove = ((int) (map.size() * 0.15)) + 1; final Iterator<Map.Entry<PooledObject<T>, K>> iter = - map.entrySet().iterator(); + map.entrySet().iterator(); while (iter.hasNext() && itemsToRemove > 0) { final Map.Entry<PooledObject<T>, K> entry = iter.next(); @@ -797,7 +804,7 @@ public class GenericKeyedObjectPool<K,T> int maxQueueLength = 0; LinkedBlockingDeque<PooledObject<T>> mostLoaded = null; K loadedKey = null; - for (Map.Entry<K, ObjectDeque<T>> entry : poolMap.entrySet()) { + for (final Map.Entry<K, ObjectDeque<T>> entry : poolMap.entrySet()) { final K k = entry.getKey(); final ObjectDeque<T> deque = entry.getValue(); if (deque != null) { @@ -835,11 +842,11 @@ public class GenericKeyedObjectPool<K,T> * {@code false} */ private boolean hasBorrowWaiters() { - for (Map.Entry<K, ObjectDeque<T>> entry : poolMap.entrySet()) { + for (final Map.Entry<K, ObjectDeque<T>> entry : poolMap.entrySet()) { final ObjectDeque<T> deque = entry.getValue(); if (deque != null) { final LinkedBlockingDeque<PooledObject<T>> pool = - deque.getIdleObjects(); + deque.getIdleObjects(); if(pool.hasTakeWaiters()) { return true; } @@ -927,16 +934,16 @@ public class GenericKeyedObjectPool<K,T> continue; } - // User provided eviction policy could throw all sorts of crazy - // exceptions. Protect against such an exception killing the - // eviction thread. + // User provided eviction policy could throw all sorts of + // crazy exceptions. Protect against such an exception + // killing the eviction thread. boolean evict; try { evict = evictionPolicy.evict(evictionConfig, underTest, poolMap.get(evictionKey).getIdleObjects().size()); } catch (final Throwable t) { - // Slightly convoluted as SwallowedExceptionListener uses - // Exception rather than Throwable + // Slightly convoluted as SwallowedExceptionListener + // uses Exception rather than Throwable PoolUtils.checkRethrow(t); swallowException(new Exception(t)); // Don't evict on error conditions @@ -1225,9 +1232,9 @@ public class GenericKeyedObjectPool<K,T> // take account of objects created in other threads. if (objectDeque == null) { objectDeque = poolMap.get(key); + } } } - } /** * Create an object using the {@link KeyedPooledObjectFactory#makeObject @@ -1351,7 +1358,9 @@ public class GenericKeyedObjectPool<K,T> public Map<String,Integer> getNumActivePerKey() { final HashMap<String,Integer> result = new HashMap<>(); - for (Entry<K, ObjectDeque<T>> entry : poolMap.entrySet()) { + final Iterator<Entry<K,ObjectDeque<T>>> iter = poolMap.entrySet().iterator(); + while (iter.hasNext()) { + final Entry<K,ObjectDeque<T>> entry = iter.next(); if (entry != null) { final K key = entry.getKey(); final ObjectDeque<T> objectDequeue = entry.getValue(); @@ -1378,10 +1387,11 @@ public class GenericKeyedObjectPool<K,T> int result = 0; if (getBlockWhenExhausted()) { + final Iterator<ObjectDeque<T>> iter = poolMap.values().iterator(); - for (ObjectDeque<T> deque : poolMap.values()) { + while (iter.hasNext()) { // Assume no overflow - result += deque.getIdleObjects().getTakeQueueLength(); + result += iter.next().getIdleObjects().getTakeQueueLength(); } } @@ -1400,7 +1410,7 @@ public class GenericKeyedObjectPool<K,T> public Map<String,Integer> getNumWaitersByKey() { final Map<String,Integer> result = new HashMap<>(); - for (Map.Entry<K, ObjectDeque<T>> entry : poolMap.entrySet()) { + for (final Map.Entry<K, ObjectDeque<T>> entry : poolMap.entrySet()) { final K k = entry.getKey(); final ObjectDeque<T> deque = entry.getValue(); if (deque != null) { @@ -1431,7 +1441,7 @@ public class GenericKeyedObjectPool<K,T> final Map<String,List<DefaultPooledObjectInfo>> result = new HashMap<>(); - for (Map.Entry<K, ObjectDeque<T>> entry : poolMap.entrySet()) { + for (final Map.Entry<K, ObjectDeque<T>> entry : poolMap.entrySet()) { final K k = entry.getKey(); final ObjectDeque<T> deque = entry.getValue(); if (deque != null) { @@ -1451,6 +1461,8 @@ public class GenericKeyedObjectPool<K,T> /** * Maintains information on the per key queue for a given key. + * + * @param <S> type of objects in the pool */ private class ObjectDeque<S> { @@ -1547,9 +1559,9 @@ public class GenericKeyedObjectPool<K,T> private volatile int maxIdlePerKey = GenericKeyedObjectPoolConfig.DEFAULT_MAX_IDLE_PER_KEY; private volatile int minIdlePerKey = - GenericKeyedObjectPoolConfig.DEFAULT_MIN_IDLE_PER_KEY; + GenericKeyedObjectPoolConfig.DEFAULT_MIN_IDLE_PER_KEY; private volatile int maxTotalPerKey = - GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL_PER_KEY; + GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL_PER_KEY; private final KeyedPooledObjectFactory<K,T> factory; private final boolean fairness; @@ -1583,7 +1595,7 @@ public class GenericKeyedObjectPool<K,T> // JMX specific attributes private static final String ONAME_BASE = - "org.apache.tomcat.dbcp.pool2:type=GenericKeyedObjectPool,name="; + "org.apache.tomcat.dbcp.pool2:type=GenericKeyedObjectPool,name="; @Override protected void toStringAppendFields(final StringBuilder builder) { Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPool.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPool.java?rev=1817096&r1=1817095&r2=1817096&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPool.java (original) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/GenericObjectPool.java Mon Dec 4 14:44:22 2017 @@ -18,7 +18,7 @@ package org.apache.tomcat.dbcp.pool2.imp import java.util.ArrayList; import java.util.HashSet; -import java.util.List; +import java.util.Iterator; import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; @@ -140,7 +140,7 @@ public class GenericObjectPool<T> extend * is set too low on heavily loaded systems it is possible you will see * objects being destroyed and almost immediately new objects being created. * This is a result of the active threads momentarily returning objects - * faster than they are requesting them them, causing the number of idle + * faster than they are requesting them, causing the number of idle * objects to rise above maxIdle. The best value for maxIdle for heavily * loaded system will vary but the default is a good starting point. * @@ -159,7 +159,7 @@ public class GenericObjectPool<T> extend * is set too low on heavily loaded systems it is possible you will see * objects being destroyed and almost immediately new objects being created. * This is a result of the active threads momentarily returning objects - * faster than they are requesting them them, causing the number of idle + * faster than they are requesting them, causing the number of idle * objects to rise above maxIdle. The best value for maxIdle for heavily * loaded system will vary but the default is a good starting point. * @@ -336,6 +336,7 @@ public class GenericObjectPool<T> extend this.abandonedConfig.setRemoveAbandonedOnMaintenance(abandonedConfig.getRemoveAbandonedOnMaintenance()); this.abandonedConfig.setRemoveAbandonedTimeout(abandonedConfig.getRemoveAbandonedTimeout()); this.abandonedConfig.setUseUsageTracking(abandonedConfig.getUseUsageTracking()); + this.abandonedConfig.setRequireFullStackTrace(abandonedConfig.getRequireFullStackTrace()); } } @@ -759,16 +760,16 @@ public class GenericObjectPool<T> extend continue; } - // User provided eviction policy could throw all sorts of crazy - // exceptions. Protect against such an exception killing the - // eviction thread. + // User provided eviction policy could throw all sorts of + // crazy exceptions. Protect against such an exception + // killing the eviction thread. boolean evict; try { evict = evictionPolicy.evict(evictionConfig, underTest, idleObjects.size()); } catch (final Throwable t) { - // Slightly convoluted as SwallowedExceptionListener uses - // Exception rather than Throwable + // Slightly convoluted as SwallowedExceptionListener + // uses Exception rather than Throwable PoolUtils.checkRethrow(t); swallowException(new Exception(t)); // Don't evict on error conditions @@ -887,7 +888,7 @@ public class GenericObjectPool<T> extend final PooledObject<T> p; try { p = factory.makeObject(); - } catch (Exception e) { + } catch (final Exception e) { createCount.decrementAndGet(); throw e; } finally { @@ -900,6 +901,10 @@ public class GenericObjectPool<T> extend final AbandonedConfig ac = this.abandonedConfig; if (ac != null && ac.getLogAbandoned()) { p.setLogAbandoned(true); + // TODO: in 3.0, this can use the method defined on PooledObject + if (p instanceof DefaultPooledObject<?>) { + ((DefaultPooledObject<T>) p).setRequireFullStackTrace(ac.getRequireFullStackTrace()); + } } createdCount.incrementAndGet(); @@ -1034,8 +1039,10 @@ public class GenericObjectPool<T> extend final long now = System.currentTimeMillis(); final long timeout = now - (ac.getRemoveAbandonedTimeout() * 1000L); - final List<PooledObject<T>> remove = new ArrayList<>(); - for (PooledObject<T> pooledObject : allObjects.values()) { + final ArrayList<PooledObject<T>> remove = new ArrayList<>(); + final Iterator<PooledObject<T>> it = allObjects.values().iterator(); + while (it.hasNext()) { + final PooledObject<T> pooledObject = it.next(); synchronized (pooledObject) { if (pooledObject.getState() == PooledObjectState.ALLOCATED && pooledObject.getLastUsedTime() <= timeout) { @@ -1046,7 +1053,9 @@ public class GenericObjectPool<T> extend } // Now remove the abandoned objects - for (PooledObject<T> pooledObject : remove) { + final Iterator<PooledObject<T>> itr = remove.iterator(); + while (itr.hasNext()) { + final PooledObject<T> pooledObject = itr.next(); if (ac.getLogAbandoned()) { pooledObject.printStackTrace(ac.getLogWriter()); } @@ -1191,4 +1200,5 @@ public class GenericObjectPool<T> extend builder.append(", abandonedConfig="); builder.append(abandonedConfig); } + } Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/LinkedBlockingDeque.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/LinkedBlockingDeque.java?rev=1817096&r1=1817095&r2=1817096&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/LinkedBlockingDeque.java (original) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/LinkedBlockingDeque.java Mon Dec 4 14:44:22 2017 @@ -88,7 +88,11 @@ class LinkedBlockingDeque<E> extends Abs private static final long serialVersionUID = -387911632671998426L; - /** Doubly-linked list node class */ + /** + * Doubly-linked list node class. + * + * @param <E> node item type + */ private static final class Node<E> { /** * The item, or null if this node has been removed. Added: tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/NoOpCallStack.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/NoOpCallStack.java?rev=1817096&view=auto ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/NoOpCallStack.java (added) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/NoOpCallStack.java Mon Dec 4 14:44:22 2017 @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tomcat.dbcp.pool2.impl; + +import java.io.PrintWriter; + +/** + * CallStack strategy using no-op implementations of all functionality. Can be used by default when abandoned object + * logging is disabled. + * + * @since 2.5 + */ +public class NoOpCallStack implements CallStack { + + public static final CallStack INSTANCE = new NoOpCallStack(); + + private NoOpCallStack() { + } + + @Override + public boolean printStackTrace(PrintWriter writer) { + return false; + } + + @Override + public void fillInStackTrace() { + // no-op + } + + @Override + public void clear() { + // no-op + } +} Propchange: tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/NoOpCallStack.java ------------------------------------------------------------------------------ svn:eol-style = native Added: tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/SecurityManagerCallStack.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/SecurityManagerCallStack.java?rev=1817096&view=auto ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/SecurityManagerCallStack.java (added) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/SecurityManagerCallStack.java Mon Dec 4 14:44:22 2017 @@ -0,0 +1,129 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tomcat.dbcp.pool2.impl; + +import java.io.PrintWriter; +import java.lang.ref.WeakReference; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.List; + +/** + * CallStack strategy using a {@link SecurityManager}. Obtaining the current call stack is much faster via a + * SecurityManger, but access to the underlying method may be restricted by the current SecurityManager. In environments + * where a SecurityManager cannot be created, {@link ThrowableCallStack} should be used instead. + * + * @see RuntimePermission + * @see SecurityManager#getClassContext() + * @since 2.4.3 + */ +public class SecurityManagerCallStack implements CallStack { + + private final String messageFormat; + //@GuardedBy("dateFormat") + private final DateFormat dateFormat; + private final PrivateSecurityManager securityManager; + + private volatile Snapshot snapshot; + + /** + * Create a new instance. + * + * @param messageFormat message format + * @param useTimestamp whether to format the dates in the output message or not + */ + public SecurityManagerCallStack(final String messageFormat, final boolean useTimestamp) { + this.messageFormat = messageFormat; + this.dateFormat = useTimestamp ? new SimpleDateFormat(messageFormat) : null; + this.securityManager = AccessController.doPrivileged(new PrivilegedAction<PrivateSecurityManager>() { + @Override + public PrivateSecurityManager run() { + return new PrivateSecurityManager(); + } + }); + } + + @Override + public boolean printStackTrace(final PrintWriter writer) { + final Snapshot snapshotRef = this.snapshot; + if (snapshotRef == null) { + return false; + } + final String message; + if (dateFormat == null) { + message = messageFormat; + } else { + synchronized (dateFormat) { + message = dateFormat.format(Long.valueOf(snapshotRef.timestamp)); + } + } + writer.println(message); + for (final WeakReference<Class<?>> reference : snapshotRef.stack) { + writer.println(reference.get()); + } + return true; + } + + @Override + public void fillInStackTrace() { + snapshot = new Snapshot(securityManager.getCallStack()); + } + + @Override + public void clear() { + snapshot = null; + } + + /** + * A custom security manager. + */ + private static class PrivateSecurityManager extends SecurityManager { + /** + * Get the class stack. + * + * @return class stack + */ + private List<WeakReference<Class<?>>> getCallStack() { + final Class<?>[] classes = getClassContext(); + final List<WeakReference<Class<?>>> stack = new ArrayList<>(classes.length); + for (final Class<?> klass : classes) { + stack.add(new WeakReference<Class<?>>(klass)); + } + return stack; + } + } + + /** + * A snapshot of a class stack. + */ + private static class Snapshot { + private final long timestamp = System.currentTimeMillis(); + private final List<WeakReference<Class<?>>> stack; + + /** + * Create a new snapshot with a class stack. + * + * @param stack class stack + */ + private Snapshot(final List<WeakReference<Class<?>>> stack) { + this.stack = stack; + } + } +} Propchange: tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/SecurityManagerCallStack.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/SoftReferenceObjectPool.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/SoftReferenceObjectPool.java?rev=1817096&r1=1817095&r2=1817096&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/SoftReferenceObjectPool.java (original) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/SoftReferenceObjectPool.java Mon Dec 4 14:44:22 2017 @@ -16,6 +16,7 @@ */ package org.apache.tomcat.dbcp.pool2.impl; +import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; import java.util.ArrayList; @@ -327,8 +328,10 @@ public class SoftReferenceObjectPool<T> @Override public synchronized void clear() { if (null != factory) { - for (PooledSoftReference<T> ref : idleReferences) { + final Iterator<PooledSoftReference<T>> iter = idleReferences.iterator(); + while (iter.hasNext()) { try { + final PooledSoftReference<T> ref = iter.next(); if (null != ref.getObject()) { factory.destroyObject(ref); } @@ -373,7 +376,9 @@ public class SoftReferenceObjectPool<T> // Remove wrappers for enqueued references from idle and allReferences lists removeClearedReferences(idleReferences.iterator()); removeClearedReferences(allReferences.iterator()); - while (refQueue.poll() != null) {} + while (refQueue.poll() != null) { + // empty + } } /** @@ -383,7 +388,9 @@ public class SoftReferenceObjectPool<T> * @return PooledSoftReference wrapping a soft reference to obj */ private PooledSoftReference<T> findReference(final T obj) { - for (PooledSoftReference<T> reference : allReferences) { + final Iterator<PooledSoftReference<T>> iterator = allReferences.iterator(); + while (iterator.hasNext()) { + final PooledSoftReference<T> reference = iterator.next(); if (reference.getObject() != null && reference.getObject().equals(obj)) { return reference; } Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/ThrowableCallStack.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/ThrowableCallStack.java?rev=1817096&r1=1817095&r2=1817096&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/ThrowableCallStack.java (original) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/pool2/impl/ThrowableCallStack.java Mon Dec 4 14:44:22 2017 @@ -21,7 +21,9 @@ import java.text.DateFormat; import java.text.SimpleDateFormat; /** - * CallStack strategy that uses the stack trace from a {@link Throwable}. + * CallStack strategy that uses the stack trace from a {@link Throwable}. This strategy, while slower than the + * SecurityManager implementation, provides call stack method names and other metadata in addition to the call stack + * of classes. * * @see Throwable#fillInStackTrace() * @since 2.4.3 @@ -34,15 +36,21 @@ public class ThrowableCallStack implemen private volatile Snapshot snapshot; + /** + * Create a new instance. + * + * @param messageFormat message format + * @param useTimestamp whether to format the dates in the output message or not + */ public ThrowableCallStack(final String messageFormat, final boolean useTimestamp) { this.messageFormat = messageFormat; this.dateFormat = useTimestamp ? new SimpleDateFormat(messageFormat) : null; } @Override - public synchronized boolean printStackTrace(PrintWriter writer) { - Snapshot snapshot = this.snapshot; - if (snapshot == null) { + public synchronized boolean printStackTrace(final PrintWriter writer) { + final Snapshot snapshotRef = this.snapshot; + if (snapshotRef == null) { return false; } final String message; @@ -50,11 +58,11 @@ public class ThrowableCallStack implemen message = messageFormat; } else { synchronized (dateFormat) { - message = dateFormat.format(Long.valueOf(snapshot.timestamp)); + message = dateFormat.format(Long.valueOf(snapshotRef.timestamp)); } } writer.println(message); - snapshot.printStackTrace(writer); + snapshotRef.printStackTrace(writer); return true; } @@ -68,8 +76,11 @@ public class ThrowableCallStack implemen snapshot = null; } + /** + * A snapshot of a throwable. + */ private static class Snapshot extends Throwable { - private static final long serialVersionUID = -7871548158947014789L; + private static final long serialVersionUID = 1L; private final long timestamp = System.currentTimeMillis(); } } Modified: tomcat/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1817096&r1=1817095&r2=1817096&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/changelog.xml (original) +++ tomcat/trunk/webapps/docs/changelog.xml Mon Dec 4 14:44:22 2017 @@ -76,6 +76,9 @@ Add missing SHA-512 hash for release artifacts to the build script. (markt) </fix> + <update> + Update the internal fork of Commons Pool 2 to 2.4.3. (markt) + </update> </changelog> </subsection> </section> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org