View Javadoc
1   /*
2    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
3    * The software in this package is published under the terms of the CPAL v1.0
4    * license, a copy of which has been included with this distribution in the
5    * LICENSE.txt file.
6    */
7   package org.mule.util.pool;
8   
9   import org.mule.api.MuleContext;
10  import org.mule.api.lifecycle.Disposable;
11  import org.mule.api.lifecycle.InitialisationException;
12  import org.mule.api.object.ObjectFactory;
13  import org.mule.config.PoolingProfile;
14  import org.mule.config.i18n.MessageFactory;
15  
16  import java.util.ArrayList;
17  import java.util.List;
18  
19  import org.apache.commons.logging.Log;
20  import org.apache.commons.logging.LogFactory;
21  import org.apache.commons.pool.PoolableObjectFactory;
22  import org.apache.commons.pool.impl.GenericObjectPool;
23  
24  /**
25   * <code>CommonsPoolProxyPool</code> is an implementation of {@link ObjectPool}
26   * that internally uses the commons-pool {@link GenericObjectPool} and uses a
27   * {@link ObjectFactory} for creating new pooled instances.
28   */
29  public class CommonsPoolObjectPool implements ObjectPool
30  {
31      /**
32       * logger used by this class
33       */
34      protected static final Log logger = LogFactory.getLog(CommonsPoolObjectPool.class);
35  
36      /**
37       * The pool
38       */
39      protected GenericObjectPool pool;
40  
41      /**
42       * The ObjectFactory used to create new pool instances
43       */
44      protected ObjectFactory objectFactory;
45  
46      /**
47       * The pooling profile used to configure and initialise pool
48       */
49      protected PoolingProfile poolingProfile;
50  
51      protected MuleContext muleContext;
52  
53      /**
54       * Creates a new pool and an Object factory with the ServiceDescriptor
55       */
56      public CommonsPoolObjectPool(ObjectFactory objectFactory, PoolingProfile poolingProfile, MuleContext muleContext)
57      {
58          this.objectFactory = objectFactory;
59          this.poolingProfile = poolingProfile;
60          this.muleContext = muleContext;
61      }
62  
63      public void initialise() throws InitialisationException
64      {
65          GenericObjectPool.Config config = new GenericObjectPool.Config();
66  
67          if (poolingProfile != null)
68          {
69              config.maxIdle = poolingProfile.getMaxIdle();
70              config.maxActive = poolingProfile.getMaxActive();
71              config.maxWait = poolingProfile.getMaxWait();
72              config.whenExhaustedAction = (byte) poolingProfile.getExhaustedAction();
73          }
74  
75          pool = new GenericObjectPool(getPooledObjectFactory(), config);
76  
77          try
78          {
79              applyInitialisationPolicy();
80          }
81          catch (Exception e)
82          {
83              throw new InitialisationException(e, this);
84          }
85      }
86  
87      /**
88       * Template method to be overridden by implementations that do more than just
89       * invoke objectFactory
90       */
91      protected PoolableObjectFactory getPooledObjectFactory()
92      {
93          return new PoolabeObjectFactoryAdapter();
94      }
95  
96      protected void applyInitialisationPolicy() throws Exception
97      {
98          if (poolingProfile != null)
99          {
100             int numToBorrow = 0;
101             int initPolicy = poolingProfile.getInitialisationPolicy();
102 
103             if (initPolicy == PoolingProfile.INITIALISE_ALL)
104             {
105                 numToBorrow = poolingProfile.getMaxActive();
106             }
107             else if (initPolicy == PoolingProfile.INITIALISE_ONE)
108             {
109                 numToBorrow = 1;
110             }
111 
112             List<Object> holderList = new ArrayList<Object>(numToBorrow);
113             try
114             {
115                 for (int t = 0; t < numToBorrow; t++)
116                 {
117                     holderList.add(getPooledObjectFactory().makeObject());
118                 }
119             }
120             finally
121             {
122                 for (int t = 0; t < holderList.size(); t++)
123                 {
124                     Object obj = holderList.get(t);
125                     if (obj != null)
126                     {
127                         this.returnObject(obj);
128                     }
129                 }
130             }
131         }
132     }
133 
134     public Object borrowObject() throws Exception
135     {
136         if (pool != null)
137         {
138             return pool.borrowObject();
139         }
140         else
141         {
142             throw new InitialisationException(
143                 MessageFactory.createStaticMessage("Object pool has not been initialized."), this);
144         }
145     }
146 
147     public void returnObject(Object object)
148     {
149         if (pool != null)
150         {
151             try
152             {
153                 pool.returnObject(object);
154             }
155             catch (Exception ex)
156             {
157                 // declared Exception is never thrown from pool; this is a known bug
158                 // in the pool API
159             }
160         }
161     }
162 
163     public int getNumActive()
164     {
165         return pool.getNumActive();
166     }
167 
168     public int getMaxActive()
169     {
170         return pool.getMaxActive();
171     }
172 
173     public void dispose()
174     {
175         if (pool != null)
176         {
177             try
178             {
179                 pool.close();
180             }
181             catch (Exception e)
182             {
183                 // close() never throws - wrong method signature
184             }
185             finally
186             {
187                 pool = null;
188             }
189         }
190     }
191 
192     public void clear()
193     {
194         if (pool != null)
195         {
196             pool.clear();
197         }
198     }
199 
200     public void close()
201     {
202         if (pool != null)
203         {
204             try
205             {
206                 pool.close();
207             }
208             catch (Exception e)
209             {
210                 // close() never throws - wrong method signature
211             }
212             finally
213             {
214                 pool = null;
215             }
216         }
217     }
218 
219     public void setObjectFactory(ObjectFactory objectFactory)
220     {
221         this.objectFactory = objectFactory;
222     }
223 
224     public ObjectFactory getObjectFactory()
225     {
226         return objectFactory;
227     }
228 
229     /**
230      * Wraps org.mule.object.ObjectFactory with commons-pool PoolableObjectFactory
231      */
232     class PoolabeObjectFactoryAdapter implements PoolableObjectFactory
233     {
234         public void activateObject(Object obj) throws Exception
235         {
236             // nothing to do
237         }
238 
239         public void destroyObject(Object obj) throws Exception
240         {
241             if (obj instanceof Disposable)
242             {
243                 ((Disposable) obj).dispose();
244             }
245         }
246 
247         public Object makeObject() throws Exception
248         {
249             return objectFactory.getInstance(muleContext);
250         }
251 
252         public void passivateObject(Object obj) throws Exception
253         {
254             // nothing to do
255         }
256 
257         public boolean validateObject(Object obj)
258         {
259             return true;
260         }
261     }
262 }