/* * Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com * The software in this package is published under the terms of the CPAL v1.0 * license, a copy of which has been included with this distribution in the * LICENSE.txt file. */ package org.mule.runtime.core.util.pool; import org.mule.runtime.api.config.PoolingProfile; import org.mule.runtime.core.api.MuleContext; import org.mule.runtime.api.lifecycle.Disposable; import org.mule.runtime.api.lifecycle.InitialisationException; import org.mule.runtime.core.api.object.ObjectFactory; import org.mule.runtime.api.i18n.I18nMessageFactory; import java.util.ArrayList; import java.util.List; import org.apache.commons.pool.PoolableObjectFactory; import org.apache.commons.pool.impl.GenericObjectPool; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * <code>CommonsPoolProxyPool</code> is an implementation of {@link ObjectPool} that internally uses the commons-pool * {@link GenericObjectPool} and uses a {@link ObjectFactory} for creating new pooled instances. */ public class CommonsPoolObjectPool implements ObjectPool { /** * logger used by this class */ protected static final Logger logger = LoggerFactory.getLogger(CommonsPoolObjectPool.class); /** * The pool */ protected GenericObjectPool pool; /** * The ObjectFactory used to create new pool instances */ protected ObjectFactory objectFactory; /** * The pooling profile used to configure and initialise pool */ protected PoolingProfile poolingProfile; protected MuleContext muleContext; /** * Creates a new pool and an Object factory with the ServiceDescriptor */ public CommonsPoolObjectPool(ObjectFactory objectFactory, PoolingProfile poolingProfile, MuleContext muleContext) { this.objectFactory = objectFactory; this.poolingProfile = poolingProfile; this.muleContext = muleContext; } public void initialise() throws InitialisationException { GenericObjectPool.Config config = new GenericObjectPool.Config(); if (poolingProfile != null) { config.maxIdle = poolingProfile.getMaxIdle(); config.maxActive = poolingProfile.getMaxActive(); config.maxWait = poolingProfile.getMaxWait(); config.whenExhaustedAction = (byte) poolingProfile.getExhaustedAction(); config.minEvictableIdleTimeMillis = poolingProfile.getMinEvictionMillis(); config.timeBetweenEvictionRunsMillis = poolingProfile.getEvictionCheckIntervalMillis(); } pool = new GenericObjectPool(getPooledObjectFactory(), config); try { applyInitialisationPolicy(); } catch (Exception e) { throw new InitialisationException(e, this); } } /** * Template method to be overridden by implementations that do more than just invoke objectFactory */ protected PoolableObjectFactory getPooledObjectFactory() { return new PoolabeObjectFactoryAdapter(); } protected void applyInitialisationPolicy() throws Exception { if (poolingProfile != null) { int numToBorrow = 0; int initPolicy = poolingProfile.getInitialisationPolicy(); if (initPolicy == PoolingProfile.INITIALISE_ALL) { numToBorrow = poolingProfile.getMaxActive(); } else if (initPolicy == PoolingProfile.INITIALISE_ONE) { numToBorrow = 1; } List<Object> holderList = new ArrayList<Object>(numToBorrow); try { for (int t = 0; t < numToBorrow; t++) { holderList.add(getPooledObjectFactory().makeObject()); } } finally { for (int t = 0; t < holderList.size(); t++) { Object obj = holderList.get(t); if (obj != null) { this.returnObject(obj); } } } } } public Object borrowObject() throws Exception { if (pool != null) { return pool.borrowObject(); } else { throw new InitialisationException(I18nMessageFactory.createStaticMessage("Object pool has not been initialized."), this); } } public void returnObject(Object object) { if (pool != null) { try { pool.returnObject(object); } catch (Exception ex) { // declared Exception is never thrown from pool; this is a known bug // in the pool API } } } public int getNumActive() { return pool.getNumActive(); } public int getMaxActive() { return pool.getMaxActive(); } public void dispose() { if (pool != null) { try { pool.close(); } catch (Exception e) { // close() never throws - wrong method signature } finally { pool = null; } } } public void clear() { if (pool != null) { pool.clear(); } } public void close() { if (pool != null) { try { pool.close(); } catch (Exception e) { // close() never throws - wrong method signature } finally { pool = null; } } } public void setObjectFactory(ObjectFactory objectFactory) { this.objectFactory = objectFactory; } public ObjectFactory getObjectFactory() { return objectFactory; } /** * Wraps org.mule.runtime.core.object.ObjectFactory with commons-pool PoolableObjectFactory */ class PoolabeObjectFactoryAdapter implements PoolableObjectFactory { public void activateObject(Object obj) throws Exception { // nothing to do } public void destroyObject(Object obj) throws Exception { if (obj instanceof Disposable) { ((Disposable) obj).dispose(); } } public Object makeObject() throws Exception { return objectFactory.getInstance(muleContext); } public void passivateObject(Object obj) throws Exception { // nothing to do } public boolean validateObject(Object obj) { return true; } } }