Author: markt Date: Thu Apr 26 20:20:10 2012 New Revision: 1331062 URL: http://svn.apache.org/viewvc?rev=1331062&view=rev Log: Start pulling the common GOP and GKOP code into a single base class.
Added: commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/BaseGenericObjectPool.java (with props) Modified: commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/GenericKeyedObjectPool.java commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/GenericObjectPool.java Added: commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/BaseGenericObjectPool.java URL: http://svn.apache.org/viewvc/commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/BaseGenericObjectPool.java?rev=1331062&view=auto ============================================================================== --- commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/BaseGenericObjectPool.java (added) +++ commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/BaseGenericObjectPool.java Thu Apr 26 20:20:10 2012 @@ -0,0 +1,221 @@ +/* + * 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.commons.pool2.impl; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.io.Writer; +import java.util.ArrayList; +import java.util.Deque; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +import javax.management.ListenerNotFoundException; +import javax.management.MBeanNotificationInfo; +import javax.management.Notification; +import javax.management.NotificationBroadcasterSupport; +import javax.management.NotificationEmitter; +import javax.management.NotificationFilter; +import javax.management.NotificationListener; +import javax.management.ObjectName; + +/** + * Base class that provides common functionality for {@link GenericObjectPool} + * and {@link GenericKeyedObjectPool}. The primary reason this class exists is + * reduce code duplication between the two pool implementations. + */ +public abstract class BaseGenericObjectPool implements NotificationEmitter { + + // Constants + /** + * Name of the JMX notification broadcast when the pool implementation + * swallows an {@link Exception}. + */ + public static final String NOTIFICATION_SWALLOWED_EXCEPTION = + "SWALLOWED_EXCEPTION"; + private static final int SWALLOWED_EXCEPTION_QUEUE_SIZE = 10; + + // Configuration attributes + // None as yet + + // Internal state attributes + protected volatile boolean closed = false; + + // Monitoring (primarily JMX) attributes + private final NotificationBroadcasterSupport jmxNotificationSupport; + private final String creationStackTrace; + private final Deque<String> swallowedExceptions = new LinkedList<String>(); + private final AtomicInteger swallowedExcpetionCount = new AtomicInteger(0); + + + public BaseGenericObjectPool(BaseObjectPoolConfig config) { + if (config.getJmxEnabled()) { + this.jmxNotificationSupport = new NotificationBroadcasterSupport(); + } else { + this.jmxNotificationSupport = null; + } + + // Populate the swallowed exceptions queue + for (int i = 0; i < SWALLOWED_EXCEPTION_QUEUE_SIZE; i++) { + swallowedExceptions.add(null); + } + + // Populate the creation stack trace + this.creationStackTrace = getStackTrace(new Exception()); + } + + /** + * Closes the pool destroys the remaining idle objects and, if registered in + * JMX, deregisters it. + */ + public abstract void close(); + + /** + * Has this pool instance been closed. + * @return <code>true</code> when this pool has been closed. + */ + public final boolean isClosed() { + return closed; + } + + + /** + * Throws an <code>IllegalStateException</code> if called when the pool has + * been closed. + * + * @throws IllegalStateException if this pool has been closed. + * @see #isClosed() + */ + protected final void assertOpen() throws IllegalStateException { + if (isClosed()) { + throw new IllegalStateException("Pool not open"); + } + } + + + // Monitoring (primarily JMX) related methods + + /** + * Provides the name under which the pool has been registered with the + * platform MBean server or <code>null</code> if the pool has not been + * registered. + */ + public abstract ObjectName getJmxName(); + + /** + * Provides the stack trace for the call that created this pool. JMX + * registration may trigger a memory leak so it is important that pools are + * deregistered when no longer used by calling the {@link #close()} method. + * This method is provided to assist with identifying code that creates but + * does not close it thereby creating a memory leak. + */ + public String getCreationStackTrace() { + return creationStackTrace; + } + + /** + * Lists the most recent exceptions that have been swallowed by the pool + * implementation. Exceptions are typically swallowed when a problem occurs + * while destroying an object. + */ + public String[] getSwallowedExceptions() { + List<String> temp = + new ArrayList<String>(SWALLOWED_EXCEPTION_QUEUE_SIZE); + synchronized (swallowedExceptions) { + temp.addAll(swallowedExceptions); + } + return temp.toArray(new String[SWALLOWED_EXCEPTION_QUEUE_SIZE]); + } + + protected final NotificationBroadcasterSupport getJmxNotificationSupport() { + return jmxNotificationSupport; + } + + protected String getStackTrace(Exception e) { + // Need the exception in string form to prevent the retention of + // references to classes in the stack trace that could trigger a memory + // leak in a container environment + Writer w = new StringWriter(); + PrintWriter pw = new PrintWriter(w); + e.printStackTrace(pw); + return w.toString(); + } + + protected void swallowException(Exception e) { + String msg = getStackTrace(e); + + ObjectName oname = getJmxName(); + if (oname != null) { + Notification n = new Notification(NOTIFICATION_SWALLOWED_EXCEPTION, + oname, swallowedExcpetionCount.incrementAndGet(), msg); + getJmxNotificationSupport().sendNotification(n); + } + + // Add the exception the queue, removing the oldest + synchronized (swallowedExceptions) { + swallowedExceptions.addLast(msg); + swallowedExceptions.pollFirst(); + } + } + + + // Implement NotificationEmitter interface + + @Override + public final void addNotificationListener(NotificationListener listener, + NotificationFilter filter, Object handback) + throws IllegalArgumentException { + + if (jmxNotificationSupport == null) { + throw new UnsupportedOperationException("JMX is not enabled"); + } + jmxNotificationSupport.addNotificationListener( + listener, filter, handback); + } + + @Override + public final void removeNotificationListener(NotificationListener listener) + throws ListenerNotFoundException { + + if (jmxNotificationSupport == null) { + throw new UnsupportedOperationException("JMX is not enabled"); + } + jmxNotificationSupport.removeNotificationListener(listener); + } + + @Override + public final MBeanNotificationInfo[] getNotificationInfo() { + + if (jmxNotificationSupport == null) { + throw new UnsupportedOperationException("JMX is not enabled"); + } + return jmxNotificationSupport.getNotificationInfo(); + } + + @Override + public final void removeNotificationListener(NotificationListener listener, + NotificationFilter filter, Object handback) + throws ListenerNotFoundException { + + if (jmxNotificationSupport == null) { + throw new UnsupportedOperationException("JMX is not enabled"); + } + jmxNotificationSupport.removeNotificationListener( + listener, filter, handback); + } +} Propchange: commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/BaseGenericObjectPool.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/GenericKeyedObjectPool.java URL: http://svn.apache.org/viewvc/commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/GenericKeyedObjectPool.java?rev=1331062&r1=1331061&r2=1331062&view=diff ============================================================================== --- commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/GenericKeyedObjectPool.java (original) +++ commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/GenericKeyedObjectPool.java Thu Apr 26 20:20:10 2012 @@ -14,15 +14,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.apache.commons.pool2.impl; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.io.Writer; import java.lang.management.ManagementFactory; import java.util.ArrayList; -import java.util.Deque; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; @@ -41,17 +36,11 @@ import java.util.concurrent.locks.ReadWr import java.util.concurrent.locks.ReentrantReadWriteLock; import javax.management.InstanceAlreadyExistsException; -import javax.management.ListenerNotFoundException; -import javax.management.MBeanNotificationInfo; +import javax.management.InstanceNotFoundException; import javax.management.MBeanRegistrationException; import javax.management.MBeanServer; import javax.management.MalformedObjectNameException; import javax.management.NotCompliantMBeanException; -import javax.management.Notification; -import javax.management.NotificationBroadcasterSupport; -import javax.management.NotificationEmitter; -import javax.management.NotificationFilter; -import javax.management.NotificationListener; import javax.management.ObjectName; import org.apache.commons.pool2.KeyedObjectPool; @@ -208,8 +197,8 @@ import org.apache.commons.pool2.PoolUtil * @version $Revision$ $Date$ * @since Pool 1.0 */ -public class GenericKeyedObjectPool<K,T> implements KeyedObjectPool<K,T>, - GenericKeyedObjectPoolMBean<K>, NotificationEmitter { +public class GenericKeyedObjectPool<K,T> extends BaseGenericObjectPool + implements KeyedObjectPool<K,T>, GenericKeyedObjectPoolMBean<K> { /** * Create a new <code>GenericKeyedObjectPool</code> using defaults. @@ -229,6 +218,7 @@ public class GenericKeyedObjectPool<K,T> */ public GenericKeyedObjectPool(KeyedPoolableObjectFactory<K,T> factory, GenericKeyedObjectPoolConfig config) { + super(config); this.factory = factory; // save the current CCL to be used later by the evictor Thread factoryClassLoader = Thread.currentThread().getContextClassLoader(); @@ -244,7 +234,6 @@ public class GenericKeyedObjectPool<K,T> if (config.getJmxEnabled()) { MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); String jmxNamePrefix = config.getJmxNamePrefix(); - this.jmxNotificationSupport = new NotificationBroadcasterSupport(); int i = 1; boolean registered = false; while (!registered) { @@ -276,18 +265,8 @@ public class GenericKeyedObjectPool<K,T> registered = true; } } - } else { - this.jmxNotificationSupport = null; } this.oname = onameTemp; - - // Populate the swallowed exceptions queue - for (int i = 0; i < SWALLOWED_EXCEPTION_QUEUE_SIZE; i++) { - swallowedExceptions.add(null); - } - - // Populate the creation stack trace - this.creationStackTrace = getStackTrace(new Exception()); } /** @@ -1049,32 +1028,6 @@ public class GenericKeyedObjectPool<K,T> } } - private void swallowException(Exception e) { - String msg = getStackTrace(e); - - if (oname != null) { - Notification n = new Notification(NOTIFICATION_SWALLOWED_EXCEPTION, - oname, swallowedExcpetionCount.incrementAndGet(), msg); - jmxNotificationSupport.sendNotification(n); - } - - // Add the exception the queue, removing the oldest - synchronized (swallowedExceptions) { - swallowedExceptions.addLast(msg); - swallowedExceptions.pollFirst(); - } - } - - private String getStackTrace(Exception e) { - // Need the exception in string form to prevent the retention of - // references to classes in the stack trace that could trigger a memory - // leak in a container environment - Writer w = new StringWriter(); - PrintWriter pw = new PrintWriter(w); - e.printStackTrace(pw); - return w.toString(); - } - /** * {@inheritDoc} @@ -1226,7 +1179,7 @@ public class GenericKeyedObjectPool<K,T> * @throws Exception */ @Override - public void close() throws Exception { + public void close() { if (isClosed()) { return; } @@ -1244,8 +1197,16 @@ public class GenericKeyedObjectPool<K,T> // This clear removes any idle objects clear(); if (oname != null) { - ManagementFactory.getPlatformMBeanServer().unregisterMBean( - oname); + try { + ManagementFactory.getPlatformMBeanServer().unregisterMBean( + oname); + } catch (MBeanRegistrationException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (InstanceNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } } // Release any threads that were waiting for an object @@ -1260,31 +1221,6 @@ public class GenericKeyedObjectPool<K,T> } - /** - * Has this pool instance been closed. - * @return <code>true</code> when this pool has been closed. - * @since Pool 1.4 - */ - @Override - public boolean isClosed() { - return closed; - } - - /** - * Throws an <code>IllegalStateException</code> when this pool has been closed. - * @throws IllegalStateException when this pool has been closed. - * @see #isClosed() - * @since Pool 1.4 - */ - protected void assertOpen() throws IllegalStateException { - if(isClosed()) { - throw new IllegalStateException("Pool not open"); - } - } - - /** Whether or not the pool is closed */ - private volatile boolean closed = false; - /** * Clears oldest 15% of objects in pool. The method sorts the @@ -2059,67 +1995,10 @@ public class GenericKeyedObjectPool<K,T> } @Override - public String[] getSwallowedExceptions() { - List<String> temp = - new ArrayList<String>(SWALLOWED_EXCEPTION_QUEUE_SIZE); - synchronized (swallowedExceptions) { - temp.addAll(swallowedExceptions); - } - return temp.toArray(new String[SWALLOWED_EXCEPTION_QUEUE_SIZE]); - } - - @Override - public void addNotificationListener(NotificationListener listener, - NotificationFilter filter, Object handback) - throws IllegalArgumentException { - - if (jmxNotificationSupport == null) { - throw new UnsupportedOperationException("JMX is not enabled"); - } - jmxNotificationSupport.addNotificationListener( - listener, filter, handback); - } - - @Override - public void removeNotificationListener(NotificationListener listener) - throws ListenerNotFoundException { - - if (jmxNotificationSupport == null) { - throw new UnsupportedOperationException("JMX is not enabled"); - } - jmxNotificationSupport.removeNotificationListener(listener); - } - - @Override - public MBeanNotificationInfo[] getNotificationInfo() { - - if (jmxNotificationSupport == null) { - throw new UnsupportedOperationException("JMX is not enabled"); - } - return jmxNotificationSupport.getNotificationInfo(); - } - - @Override - public void removeNotificationListener(NotificationListener listener, - NotificationFilter filter, Object handback) - throws ListenerNotFoundException { - - if (jmxNotificationSupport == null) { - throw new UnsupportedOperationException("JMX is not enabled"); - } - jmxNotificationSupport.removeNotificationListener( - listener, filter, handback); - } - public ObjectName getJmxName() { return oname; } - @Override - public String getCreationStackTrace() { - return creationStackTrace; - } - //--- inner classes ---------------------------------------------- /** @@ -2479,15 +2358,7 @@ public class GenericKeyedObjectPool<K,T> private final Object maxBorrowWaitTimeMillisLock = new Object(); private volatile long maxBorrowWaitTimeMillis = 0; // @GuardedBy("maxBorrowWaitTimeMillisLock") - public static final String NOTIFICATION_SWALLOWED_EXCEPTION = - "SWALLOWED_EXCEPTION"; - private static final int SWALLOWED_EXCEPTION_QUEUE_SIZE = 10; - private final Deque<String> swallowedExceptions = new LinkedList<String>(); - private final AtomicInteger swallowedExcpetionCount = new AtomicInteger(0); - private final ObjectName oname; - private final NotificationBroadcasterSupport jmxNotificationSupport; - private final String creationStackTrace; private static final String ONAME_BASE = "org.apache.commoms.pool2:type=GenericKeyedObjectPool,name="; Modified: commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/GenericObjectPool.java URL: http://svn.apache.org/viewvc/commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/GenericObjectPool.java?rev=1331062&r1=1331061&r2=1331062&view=diff ============================================================================== --- commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/GenericObjectPool.java (original) +++ commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/GenericObjectPool.java Thu Apr 26 20:20:10 2012 @@ -16,12 +16,8 @@ */ package org.apache.commons.pool2.impl; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.io.Writer; import java.lang.management.ManagementFactory; import java.util.ArrayList; -import java.util.Deque; import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -30,24 +26,16 @@ import java.util.NoSuchElementException; import java.util.TimerTask; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import javax.management.InstanceAlreadyExistsException; -import javax.management.ListenerNotFoundException; -import javax.management.MBeanNotificationInfo; +import javax.management.InstanceNotFoundException; import javax.management.MBeanRegistrationException; import javax.management.MBeanServer; import javax.management.MalformedObjectNameException; import javax.management.NotCompliantMBeanException; -import javax.management.Notification; -import javax.management.NotificationBroadcasterSupport; -import javax.management.NotificationEmitter; -import javax.management.NotificationFilter; -import javax.management.NotificationListener; import javax.management.ObjectName; -import org.apache.commons.pool2.BaseObjectPool; import org.apache.commons.pool2.ObjectPool; import org.apache.commons.pool2.PoolUtils; import org.apache.commons.pool2.PoolableObjectFactory; @@ -174,8 +162,8 @@ import org.apache.commons.pool2.Poolable * 2011) $ * @since Pool 1.0 */ -public class GenericObjectPool<T> extends BaseObjectPool<T> - implements GenericObjectPoolMBean, NotificationEmitter { +public class GenericObjectPool<T> extends BaseGenericObjectPool + implements ObjectPool<T>, GenericObjectPoolMBean { /** * Create a new <code>GenericObjectPool</code> using default. @@ -195,6 +183,7 @@ public class GenericObjectPool<T> extend */ public GenericObjectPool(PoolableObjectFactory<T> factory, GenericObjectPoolConfig config) { + super(config); this.factory = factory; // save the current CCL to be used later by the evictor Thread factoryClassLoader = Thread.currentThread().getContextClassLoader(); @@ -210,7 +199,6 @@ public class GenericObjectPool<T> extend if (config.getJmxEnabled()) { MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); String jmxNamePrefix = config.getJmxNamePrefix(); - this.jmxNotificationSupport = new NotificationBroadcasterSupport(); int i = 1; boolean registered = false; while (!registered) { @@ -242,18 +230,8 @@ public class GenericObjectPool<T> extend registered = true; } } - } else { - this.jmxNotificationSupport = null; } this.oname = onameTemp; - - // Populate the swallowed exceptions queue - for (int i = 0; i < SWALLOWED_EXCEPTION_QUEUE_SIZE; i++) { - swallowedExceptions.add(null); - } - - // Populate the creation stack trace - this.creationStackTrace = getStackTrace(new Exception()); } /** @@ -976,32 +954,6 @@ public class GenericObjectPool<T> extend } } - private void swallowException(Exception e) { - String msg = getStackTrace(e); - - if (oname != null) { - Notification n = new Notification(NOTIFICATION_SWALLOWED_EXCEPTION, - oname, swallowedExcpetionCount.incrementAndGet(), msg); - jmxNotificationSupport.sendNotification(n); - } - - // Add the exception the queue, removing the oldest - synchronized (swallowedExceptions) { - swallowedExceptions.addLast(msg); - swallowedExceptions.pollFirst(); - } - } - - private String getStackTrace(Exception e) { - // Need the exception in string form to prevent the retention of - // references to classes in the stack trace that could trigger a memory - // leak in a container environment - Writer w = new StringWriter(); - PrintWriter pw = new PrintWriter(w); - e.printStackTrace(pw); - return w.toString(); - } - /** * {@inheritDoc} * <p> @@ -1089,7 +1041,7 @@ public class GenericObjectPool<T> extend * @throws Exception */ @Override - public void close() throws Exception { + public void close() { if (isClosed()) { return; } @@ -1103,12 +1055,20 @@ public class GenericObjectPool<T> extend // assertOpen() startEvictor(-1L); - super.close(); + closed = true; // This clear removes any idle objects clear(); if (oname != null) { - ManagementFactory.getPlatformMBeanServer().unregisterMBean( - oname); + try { + ManagementFactory.getPlatformMBeanServer().unregisterMBean( + oname); + } catch (MBeanRegistrationException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (InstanceNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } } // Release any threads that were waiting for an object @@ -1459,67 +1419,10 @@ public class GenericObjectPool<T> extend } @Override - public String[] getSwallowedExceptions() { - List<String> temp = - new ArrayList<String>(SWALLOWED_EXCEPTION_QUEUE_SIZE); - synchronized (swallowedExceptions) { - temp.addAll(swallowedExceptions); - } - return temp.toArray(new String[SWALLOWED_EXCEPTION_QUEUE_SIZE]); - } - - @Override - public void addNotificationListener(NotificationListener listener, - NotificationFilter filter, Object handback) - throws IllegalArgumentException { - - if (jmxNotificationSupport == null) { - throw new UnsupportedOperationException("JMX is not enabled"); - } - jmxNotificationSupport.addNotificationListener( - listener, filter, handback); - } - - @Override - public void removeNotificationListener(NotificationListener listener) - throws ListenerNotFoundException { - - if (jmxNotificationSupport == null) { - throw new UnsupportedOperationException("JMX is not enabled"); - } - jmxNotificationSupport.removeNotificationListener(listener); - } - - @Override - public MBeanNotificationInfo[] getNotificationInfo() { - - if (jmxNotificationSupport == null) { - throw new UnsupportedOperationException("JMX is not enabled"); - } - return jmxNotificationSupport.getNotificationInfo(); - } - - @Override - public void removeNotificationListener(NotificationListener listener, - NotificationFilter filter, Object handback) - throws ListenerNotFoundException { - - if (jmxNotificationSupport == null) { - throw new UnsupportedOperationException("JMX is not enabled"); - } - jmxNotificationSupport.removeNotificationListener( - listener, filter, handback); - } - public ObjectName getJmxName() { return oname; } - @Override - public String getCreationStackTrace() { - return creationStackTrace; - } - // --- inner classes ---------------------------------------------- /** @@ -1779,15 +1682,7 @@ public class GenericObjectPool<T> extend private final Object maxBorrowWaitTimeMillisLock = new Object(); private volatile long maxBorrowWaitTimeMillis = 0; // @GuardedBy("maxBorrowWaitTimeMillisLock") - public static final String NOTIFICATION_SWALLOWED_EXCEPTION = - "SWALLOWED_EXCEPTION"; - private static final int SWALLOWED_EXCEPTION_QUEUE_SIZE = 10; - private final Deque<String> swallowedExceptions = new LinkedList<String>(); - private final AtomicInteger swallowedExcpetionCount = new AtomicInteger(0); - private final ObjectName oname; - private final NotificationBroadcasterSupport jmxNotificationSupport; - private final String creationStackTrace; private static final String ONAME_BASE = "org.apache.commoms.pool2:type=GenericObjectPool,name=";