001: /*
002: * Copyright 2002-2007 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.aop.target;
018:
019: import org.apache.commons.pool.ObjectPool;
020: import org.apache.commons.pool.PoolableObjectFactory;
021: import org.apache.commons.pool.impl.GenericObjectPool;
022:
023: import org.springframework.beans.BeansException;
024: import org.springframework.core.Constants;
025:
026: /**
027: * TargetSource implementation that holds objects in a configurable
028: * Jakarta Commons Pool.
029: *
030: * <p>By default, an instance of <code>GenericObjectPool</code> is created.
031: * Subclasses may change the type of <code>ObjectPool</code> used by
032: * overriding the <code>createObjectPool()</code> method.
033: *
034: * <p>Provides many configuration properties mirroring those of the Commons Pool
035: * <code>GenericObjectPool</code> class; these properties are passed to the
036: * <code>GenericObjectPool</code> during construction. If creating a subclass of this
037: * class to change the <code>ObjectPool</code> implementation type, pass in the values
038: * of configuration properties that are relevant to your chosen implementation.
039: *
040: * <p>The <code>testOnBorrow</code>, <code>testOnReturn</code> and <code>testWhileIdle</code>
041: * properties are explictly not mirrored because the implementation of
042: * <code>PoolableObjectFactory</code> used by this class does not implement
043: * meaningful validation. All exposed Commons Pool properties use the corresponding
044: * Commons Pool defaults: for example,
045: *
046: * @author Rod Johnson
047: * @author Rob Harrop
048: * @author Juergen Hoeller
049: * @see GenericObjectPool
050: * @see #createObjectPool()
051: * @see #setMaxSize
052: * @see #setMaxIdle
053: * @see #setMinIdle
054: * @see #setMaxWait
055: * @see #setTimeBetweenEvictionRunsMillis
056: * @see #setMinEvictableIdleTimeMillis
057: */
058: public class CommonsPoolTargetSource extends
059: AbstractPoolingTargetSource implements PoolableObjectFactory {
060:
061: private static final Constants constants = new Constants(
062: GenericObjectPool.class);
063:
064: private int maxIdle = GenericObjectPool.DEFAULT_MAX_IDLE;
065:
066: private int minIdle = GenericObjectPool.DEFAULT_MIN_IDLE;
067:
068: private long maxWait = GenericObjectPool.DEFAULT_MAX_WAIT;
069:
070: private long timeBetweenEvictionRunsMillis = GenericObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
071:
072: private long minEvictableIdleTimeMillis = GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
073:
074: private byte whenExhaustedAction = GenericObjectPool.DEFAULT_WHEN_EXHAUSTED_ACTION;
075:
076: /**
077: * The Jakarta Commons <code>ObjectPool</code> used to pool target objects
078: */
079: private ObjectPool pool;
080:
081: /**
082: * Create a CommonsPoolTargetSource with default settings.
083: * Default maximum size of the pool is 8.
084: * @see #setMaxSize
085: * @see GenericObjectPool#setMaxActive
086: */
087: public CommonsPoolTargetSource() {
088: setMaxSize(GenericObjectPool.DEFAULT_MAX_ACTIVE);
089: }
090:
091: /**
092: * Set the maximum number of idle objects in the pool.
093: * Default is 8.
094: * @see GenericObjectPool#setMaxIdle
095: */
096: public void setMaxIdle(int maxIdle) {
097: this .maxIdle = maxIdle;
098: }
099:
100: /**
101: * Return the maximum number of idle objects in the pool.
102: */
103: public int getMaxIdle() {
104: return this .maxIdle;
105: }
106:
107: /**
108: * Set the minimum number of idle objects in the pool.
109: * Default is 0.
110: * @see GenericObjectPool#setMinIdle
111: */
112: public void setMinIdle(int minIdle) {
113: this .minIdle = minIdle;
114: }
115:
116: /**
117: * Return the minimum number of idle objects in the pool.
118: */
119: public int getMinIdle() {
120: return this .minIdle;
121: }
122:
123: /**
124: * Set the maximum waiting time for fetching an object from the pool.
125: * Default is -1, waiting forever.
126: * @see GenericObjectPool#setMaxWait
127: */
128: public void setMaxWait(long maxWait) {
129: this .maxWait = maxWait;
130: }
131:
132: /**
133: * Return the maximum waiting time for fetching an object from the pool.
134: */
135: public long getMaxWait() {
136: return this .maxWait;
137: }
138:
139: /**
140: * Set the time between eviction runs that check idle objects whether
141: * they have been idle for too long or have become invalid.
142: * Default is -1, not performing any eviction.
143: * @see GenericObjectPool#setTimeBetweenEvictionRunsMillis
144: */
145: public void setTimeBetweenEvictionRunsMillis(
146: long timeBetweenEvictionRunsMillis) {
147: this .timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
148: }
149:
150: /**
151: * Return the time between eviction runs that check idle objects.
152: */
153: public long getTimeBetweenEvictionRunsMillis() {
154: return this .timeBetweenEvictionRunsMillis;
155: }
156:
157: /**
158: * Set the minimum time that an idle object can sit in the pool before
159: * it becomes subject to eviction. Default is 1800000 (30 minutes).
160: * <p>Note that eviction runs need to be performed to take this
161: * setting into effect.
162: * @see #setTimeBetweenEvictionRunsMillis
163: * @see GenericObjectPool#setMinEvictableIdleTimeMillis
164: */
165: public void setMinEvictableIdleTimeMillis(
166: long minEvictableIdleTimeMillis) {
167: this .minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
168: }
169:
170: /**
171: * Return the minimum time that an idle object can sit in the pool.
172: */
173: public long getMinEvictableIdleTimeMillis() {
174: return this .minEvictableIdleTimeMillis;
175: }
176:
177: /**
178: * Set the action to take when the pool is exhausted. Uses the
179: * constant names defined in Commons Pool's GenericObjectPool class:
180: * "WHEN_EXHAUSTED_BLOCK", "WHEN_EXHAUSTED_FAIL", "WHEN_EXHAUSTED_GROW".
181: * @see #setWhenExhaustedAction(byte)
182: */
183: public void setWhenExhaustedActionName(
184: String whenExhaustedActionName) {
185: setWhenExhaustedAction(constants.asNumber(
186: whenExhaustedActionName).byteValue());
187: }
188:
189: /**
190: * Set the action to take when the pool is exhausted. Uses the
191: * constant values defined in Commons Pool's GenericObjectPool class.
192: * @see GenericObjectPool#setWhenExhaustedAction(byte)
193: * @see GenericObjectPool#WHEN_EXHAUSTED_BLOCK
194: * @see GenericObjectPool#WHEN_EXHAUSTED_FAIL
195: * @see GenericObjectPool#WHEN_EXHAUSTED_GROW
196: */
197: public void setWhenExhaustedAction(byte whenExhaustedAction) {
198: this .whenExhaustedAction = whenExhaustedAction;
199: }
200:
201: /**
202: * Return the action to take when the pool is exhausted.
203: */
204: public byte getWhenExhaustedAction() {
205: return whenExhaustedAction;
206: }
207:
208: /**
209: * Creates and holds an ObjectPool instance.
210: * @see #createObjectPool()
211: */
212: protected final void createPool() {
213: logger.debug("Creating Commons object pool");
214: this .pool = createObjectPool();
215: }
216:
217: /**
218: * Subclasses can override this if they want to return a specific Commons pool.
219: * They should apply any configuration properties to the pool here.
220: * <p>Default is a GenericObjectPool instance with the given pool size.
221: * @return an empty Commons <code>ObjectPool</code>.
222: * @see org.apache.commons.pool.impl.GenericObjectPool
223: * @see #setMaxSize
224: */
225: protected ObjectPool createObjectPool() {
226: GenericObjectPool gop = new GenericObjectPool(this );
227: gop.setMaxActive(getMaxSize());
228: gop.setMaxIdle(getMaxIdle());
229: gop.setMinIdle(getMinIdle());
230: gop.setMaxWait(getMaxWait());
231: gop
232: .setTimeBetweenEvictionRunsMillis(getTimeBetweenEvictionRunsMillis());
233: gop
234: .setMinEvictableIdleTimeMillis(getMinEvictableIdleTimeMillis());
235: gop.setWhenExhaustedAction(getWhenExhaustedAction());
236: return gop;
237: }
238:
239: /**
240: * Borrow an object from the <code>ObjectPool</code>.
241: */
242: public Object getTarget() throws Exception {
243: return this .pool.borrowObject();
244: }
245:
246: /**
247: * Returns the specified object to the underlying <code>ObjectPool</code>.
248: */
249: public void releaseTarget(Object target) throws Exception {
250: this .pool.returnObject(target);
251: }
252:
253: public int getActiveCount() throws UnsupportedOperationException {
254: return this .pool.getNumActive();
255: }
256:
257: public int getIdleCount() throws UnsupportedOperationException {
258: return this .pool.getNumIdle();
259: }
260:
261: /**
262: * Closes the underlying <code>ObjectPool</code> when destroying this object.
263: */
264: public void destroy() throws Exception {
265: logger.debug("Closing Commons ObjectPool");
266: this .pool.close();
267: }
268:
269: //----------------------------------------------------------------------------
270: // Implementation of org.apache.commons.pool.PoolableObjectFactory interface
271: //----------------------------------------------------------------------------
272:
273: public Object makeObject() throws BeansException {
274: return newPrototypeInstance();
275: }
276:
277: public void destroyObject(Object obj) throws Exception {
278: destroyPrototypeInstance(obj);
279: }
280:
281: public boolean validateObject(Object obj) {
282: return true;
283: }
284:
285: public void activateObject(Object obj) {
286: }
287:
288: public void passivateObject(Object obj) {
289: }
290:
291: }
|