1. /*
  2. * Copyright 1999-2004 The Apache Software Foundation.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package org.apache.commons.pool.impl;
  17. import java.lang.ref.SoftReference;
  18. import java.util.ArrayList;
  19. import java.util.Iterator;
  20. import java.util.List;
  21. import java.util.NoSuchElementException;
  22. import org.apache.commons.pool.BaseObjectPool;
  23. import org.apache.commons.pool.ObjectPool;
  24. import org.apache.commons.pool.PoolableObjectFactory;
  25. /**
  26. * A {@link java.lang.ref.SoftReference SoftReference} based
  27. * {@link ObjectPool}.
  28. *
  29. * @author Rodney Waldhoff
  30. * @version $Revision: 1.12 $ $Date: 2004/02/28 11:46:33 $
  31. */
  32. public class SoftReferenceObjectPool extends BaseObjectPool implements ObjectPool {
  33. public SoftReferenceObjectPool() {
  34. _pool = new ArrayList();
  35. _factory = null;
  36. }
  37. public SoftReferenceObjectPool(PoolableObjectFactory factory) {
  38. _pool = new ArrayList();
  39. _factory = factory;
  40. }
  41. public SoftReferenceObjectPool(PoolableObjectFactory factory, int initSize) throws Exception {
  42. _pool = new ArrayList();
  43. _factory = factory;
  44. if(null != _factory) {
  45. for(int i=0;i<initSize;i++) {
  46. Object obj = _factory.makeObject();
  47. _factory.passivateObject(obj);
  48. _pool.add(new SoftReference(obj));
  49. }
  50. }
  51. }
  52. public synchronized Object borrowObject() throws Exception {
  53. assertOpen();
  54. Object obj = null;
  55. while(null == obj) {
  56. if(_pool.isEmpty()) {
  57. if(null == _factory) {
  58. throw new NoSuchElementException();
  59. } else {
  60. obj = _factory.makeObject();
  61. }
  62. } else {
  63. SoftReference ref = (SoftReference)(_pool.remove(_pool.size() - 1));
  64. obj = ref.get();
  65. }
  66. }
  67. if(null != _factory && null != obj) {
  68. _factory.activateObject(obj);
  69. }
  70. _numActive++;
  71. return obj;
  72. }
  73. public void returnObject(Object obj) throws Exception {
  74. assertOpen();
  75. boolean success = true;
  76. if(!(_factory.validateObject(obj))) {
  77. success = false;
  78. } else {
  79. try {
  80. _factory.passivateObject(obj);
  81. } catch(Exception e) {
  82. success = false;
  83. }
  84. }
  85. boolean shouldDestroy = !success;
  86. synchronized(this) {
  87. _numActive--;
  88. if(success) {
  89. _pool.add(new SoftReference(obj));
  90. }
  91. notifyAll(); // _numActive has changed
  92. }
  93. if(shouldDestroy) {
  94. try {
  95. _factory.destroyObject(obj);
  96. } catch(Exception e) {
  97. // ignored
  98. }
  99. }
  100. }
  101. public synchronized void invalidateObject(Object obj) throws Exception {
  102. assertOpen();
  103. _numActive--;
  104. _factory.destroyObject(obj);
  105. notifyAll(); // _numActive has changed
  106. }
  107. /**
  108. * Create an object, and place it into the pool.
  109. * addObject() is useful for "pre-loading" a pool with idle objects.
  110. */
  111. public void addObject() throws Exception {
  112. Object obj = _factory.makeObject();
  113. synchronized(this) {
  114. _numActive++; // A little slimy - must do this because returnObject decrements it.
  115. this.returnObject(obj);
  116. }
  117. }
  118. /** Returns an approximation not less than the of the number of idle instances in the pool. */
  119. public int getNumIdle() {
  120. return _pool.size();
  121. }
  122. public int getNumActive() {
  123. return _numActive;
  124. }
  125. public synchronized void clear() {
  126. assertOpen();
  127. if(null != _factory) {
  128. Iterator iter = _pool.iterator();
  129. while(iter.hasNext()) {
  130. try {
  131. Object obj = ((SoftReference)iter.next()).get();
  132. if(null != obj) {
  133. _factory.destroyObject(obj);
  134. }
  135. } catch(Exception e) {
  136. // ignore error, keep destroying the rest
  137. }
  138. }
  139. }
  140. _pool.clear();
  141. }
  142. synchronized public void close() throws Exception {
  143. clear();
  144. _pool = null;
  145. _factory = null;
  146. super.close();
  147. }
  148. synchronized public void setFactory(PoolableObjectFactory factory) throws IllegalStateException {
  149. assertOpen();
  150. if(0 < getNumActive()) {
  151. throw new IllegalStateException("Objects are already active");
  152. } else {
  153. clear();
  154. _factory = factory;
  155. }
  156. }
  157. /** My pool. */
  158. private List _pool = null;
  159. /** My {@link PoolableObjectFactory}. */
  160. private PoolableObjectFactory _factory = null;
  161. /** Number of active objects. */
  162. private int _numActive = 0;
  163. }