Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
PersistenceBrokerFactoryDefaultImpl |
|
| 1.6875;1.688 | ||||
PersistenceBrokerFactoryDefaultImpl$PBKeyedPoolableObjectFactory |
|
| 1.6875;1.688 |
1 | package org.apache.ojb.broker.core; | |
2 | ||
3 | /* Copyright 2003-2005 The Apache Software Foundation | |
4 | * | |
5 | * Licensed under the Apache License, Version 2.0 (the "License"); | |
6 | * you may not use this file except in compliance with the License. | |
7 | * You may obtain a copy of the License at | |
8 | * | |
9 | * http://www.apache.org/licenses/LICENSE-2.0 | |
10 | * | |
11 | * Unless required by applicable law or agreed to in writing, software | |
12 | * distributed under the License is distributed on an "AS IS" BASIS, | |
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 | * See the License for the specific language governing permissions and | |
15 | * limitations under the License. | |
16 | */ | |
17 | ||
18 | import java.util.Properties; | |
19 | ||
20 | import org.apache.commons.lang.builder.ToStringBuilder; | |
21 | import org.apache.commons.lang.builder.ToStringStyle; | |
22 | import org.apache.commons.pool.KeyedObjectPool; | |
23 | import org.apache.commons.pool.KeyedPoolableObjectFactory; | |
24 | import org.apache.commons.pool.impl.GenericKeyedObjectPool; | |
25 | import org.apache.ojb.broker.PBFactoryException; | |
26 | import org.apache.ojb.broker.PBKey; | |
27 | import org.apache.ojb.broker.PBState; | |
28 | import org.apache.ojb.broker.PersistenceBroker; | |
29 | import org.apache.ojb.broker.PersistenceBrokerInternal; | |
30 | import org.apache.ojb.broker.util.BrokerHelper; | |
31 | import org.apache.ojb.broker.util.logging.Logger; | |
32 | import org.apache.ojb.broker.util.logging.LoggerFactory; | |
33 | ||
34 | /** | |
35 | * This is the default implementation of the {@link PersistenceBrokerFactoryIF} | |
36 | * interface. | |
37 | * <p> | |
38 | * This implementation use a pool of {@link org.apache.ojb.broker.PersistenceBroker} | |
39 | * instances [abbr. PB]. Each pooled PB instance (the implementation class was specified | |
40 | * in OJB configuration file) is wrapped by {@link PoolablePersistenceBroker} class | |
41 | * before add to pool. | |
42 | * </p> | |
43 | * <p> | |
44 | * When calling {@link #createPersistenceBroker} or {@link #defaultPersistenceBroker} the pooled-PB | |
45 | * instance (<tt>PoolablePersistenceBroker</tt>) on its part was wrapped with {@link PersistenceBrokerHandle} | |
46 | * handle. | |
47 | * </p> | |
48 | * <p> | |
49 | * When a client do a PB.close() call on the handle the wrapped <tt>PoolablePersistenceBroker</tt> will | |
50 | * be closed and returned to pool. All further method calls on the handle | |
51 | * (except <tt>PB.isClosed()</tt> and <tt>PB.isInTransaction()</tt>) result in an exception. | |
52 | * </p> | |
53 | * Each different {@link org.apache.ojb.broker.PBKey} (based on <code>PBKey.equals(...)</code> method) | |
54 | * get its own PB-pool. | |
55 | * | |
56 | * @see PersistenceBrokerFactoryBaseImpl | |
57 | * | |
58 | * @author <a href="mailto:thma@apache.org">Thomas Mahler<a> | |
59 | * @author <a href="mailto:armin@codeAuLait.de">Armin Waibel</a> | |
60 | * @version $Id: PersistenceBrokerFactoryDefaultImpl.java,v 1.1 2007-08-24 22:17:35 ewestfal Exp $ | |
61 | */ | |
62 | public class PersistenceBrokerFactoryDefaultImpl extends PersistenceBrokerFactoryBaseImpl | |
63 | { | |
64 | private static Logger log = LoggerFactory.getLogger(PersistenceBrokerFactoryDefaultImpl.class); | |
65 | private GenericKeyedObjectPool brokerPool; | |
66 | private PBPoolInfo poolConfig; | |
67 | ||
68 | public PersistenceBrokerFactoryDefaultImpl() | |
69 | { | |
70 | super(); | |
71 | // get PB-pool configuration properties from OJB.properties | |
72 | poolConfig = new PBPoolInfo(); | |
73 | // setup pool for PB instances | |
74 | brokerPool = this.createPool(); | |
75 | log.info("Create PersistenceBroker instance pool, pool configuration was " + getPoolConfiguration()); | |
76 | } | |
77 | ||
78 | /** | |
79 | * Return broker instance from pool. If given {@link PBKey} was not found in pool | |
80 | * a new pool for given | |
81 | * @param pbKey | |
82 | * @return | |
83 | * @throws PBFactoryException | |
84 | */ | |
85 | public PersistenceBrokerInternal createPersistenceBroker(PBKey pbKey) throws PBFactoryException | |
86 | { | |
87 | if (log.isDebugEnabled()) log.debug("Obtain broker from pool, used PBKey is " + pbKey); | |
88 | PersistenceBrokerInternal broker = null; | |
89 | ||
90 | /* | |
91 | try to find a valid PBKey, if given key does not full match | |
92 | */ | |
93 | pbKey = BrokerHelper.crossCheckPBKey(pbKey); | |
94 | ||
95 | try | |
96 | { | |
97 | /* | |
98 | get a pooled PB instance, the pool is reponsible to create new | |
99 | PB instances if not found in pool | |
100 | */ | |
101 | broker = ((PersistenceBrokerInternal) brokerPool.borrowObject(pbKey)); | |
102 | /* | |
103 | now warp pooled PB instance with a handle to avoid PB corruption | |
104 | of closed PB instances. | |
105 | */ | |
106 | broker = wrapRequestedBrokerInstance(broker); | |
107 | ||
108 | } | |
109 | catch (Exception e) | |
110 | { | |
111 | try | |
112 | { | |
113 | // if something going wrong, tryto close broker | |
114 | if(broker != null) broker.close(); | |
115 | } | |
116 | catch (Exception ignore) | |
117 | { | |
118 | //ignore it | |
119 | } | |
120 | throw new PBFactoryException("Borrow broker from pool failed, using PBKey " + pbKey, e); | |
121 | } | |
122 | return broker; | |
123 | } | |
124 | ||
125 | /** | |
126 | * Each real pooled {@link PersistenceBroker} instance was wrapped by a | |
127 | * pooling handle when a new instance was created. | |
128 | * | |
129 | * @see PoolablePersistenceBroker | |
130 | * @param broker real {@link PersistenceBroker} instance | |
131 | * @param pool use {@link KeyedObjectPool} | |
132 | * @return wrapped broker instance | |
133 | */ | |
134 | protected PersistenceBrokerInternal wrapBrokerWithPoolingHandle(PersistenceBrokerInternal broker, KeyedObjectPool pool) | |
135 | { | |
136 | return new PoolablePersistenceBroker(broker, pool); | |
137 | } | |
138 | ||
139 | /** | |
140 | * Wraps the requested pooled broker instance. The returned handle | |
141 | * warps a pooled broker instance to avoid corruption | |
142 | * of already closed broker instances. | |
143 | * | |
144 | * @see PersistenceBrokerHandle | |
145 | * @param broker | |
146 | * @return The broker handle. | |
147 | */ | |
148 | protected PersistenceBrokerInternal wrapRequestedBrokerInstance(PersistenceBrokerInternal broker) | |
149 | { | |
150 | return new PersistenceBrokerHandle(broker); | |
151 | } | |
152 | ||
153 | /** | |
154 | * @see PersistenceBrokerFactoryIF#releaseAllInstances() | |
155 | */ | |
156 | public synchronized void releaseAllInstances() | |
157 | { | |
158 | log.warn("Release all instances referenced by this object"); | |
159 | super.releaseAllInstances(); | |
160 | try | |
161 | { | |
162 | brokerPool.close(); | |
163 | brokerPool = this.createPool(); | |
164 | } | |
165 | catch (Exception e) | |
166 | { | |
167 | log.error("Error while release all pooled broker instances and refresh pool", e); | |
168 | } | |
169 | } | |
170 | ||
171 | public void shutdown() | |
172 | { | |
173 | try | |
174 | { | |
175 | brokerPool.close(); | |
176 | brokerPool = null; | |
177 | } | |
178 | catch(Exception e) | |
179 | { | |
180 | log.error("Error while shutdown of broker pool", e); | |
181 | } | |
182 | super.shutdown(); | |
183 | } | |
184 | ||
185 | public int activePersistenceBroker() | |
186 | { | |
187 | return brokerPool.getNumActive(); | |
188 | } | |
189 | ||
190 | /** | |
191 | * could be used for monitoring | |
192 | * TODO: is this useful? | |
193 | */ | |
194 | public Properties getPoolConfiguration() | |
195 | { | |
196 | return poolConfig; | |
197 | } | |
198 | ||
199 | /** | |
200 | * could be used for runtime configuration | |
201 | * TODO: is this useful? | |
202 | */ | |
203 | public void setPoolConfiguration(Properties prop) | |
204 | { | |
205 | poolConfig = new PBPoolInfo(prop); | |
206 | log.info("Change pooling configuration properties: " + poolConfig.getKeyedObjectPoolConfig()); | |
207 | brokerPool.setConfig(poolConfig.getKeyedObjectPoolConfig()); | |
208 | } | |
209 | ||
210 | ||
211 | /** | |
212 | * Create the {@link org.apache.commons.pool.KeyedObjectPool}, pooling | |
213 | * the {@link PersistenceBroker} instances - override this method to | |
214 | * implement your own pool and {@link org.apache.commons.pool.KeyedPoolableObjectFactory}. | |
215 | */ | |
216 | private GenericKeyedObjectPool createPool() | |
217 | { | |
218 | GenericKeyedObjectPool.Config conf = poolConfig.getKeyedObjectPoolConfig(); | |
219 | if (log.isDebugEnabled()) | |
220 | log.debug("PersistenceBroker pool will be setup with the following configuration " + | |
221 | ToStringBuilder.reflectionToString(conf, ToStringStyle.MULTI_LINE_STYLE)); | |
222 | GenericKeyedObjectPool pool = new GenericKeyedObjectPool(null, conf); | |
223 | pool.setFactory(new PersistenceBrokerFactoryDefaultImpl.PBKeyedPoolableObjectFactory(this, pool)); | |
224 | return pool; | |
225 | } | |
226 | ||
227 | //************************************************************************************** | |
228 | // Inner classes | |
229 | //************************************************************************************** | |
230 | // | |
231 | ||
232 | /** | |
233 | * This is a {@link org.apache.commons.pool.KeyedPoolableObjectFactory} implementation, | |
234 | * manage the life-cycle of {@link PersistenceBroker} instances | |
235 | * hold in an {@link org.apache.commons.pool.KeyedObjectPool}. | |
236 | * | |
237 | * @author <a href="mailto:armin@codeAuLait.de">Armin Waibel</a> | |
238 | */ | |
239 | class PBKeyedPoolableObjectFactory implements KeyedPoolableObjectFactory | |
240 | { | |
241 | private PersistenceBrokerFactoryDefaultImpl pbf; | |
242 | private KeyedObjectPool pool; | |
243 | ||
244 | public PBKeyedPoolableObjectFactory(PersistenceBrokerFactoryDefaultImpl pbf, KeyedObjectPool pool) | |
245 | { | |
246 | this.pbf = pbf; | |
247 | this.pool = pool; | |
248 | } | |
249 | ||
250 | public Object makeObject(Object key) throws Exception | |
251 | { | |
252 | return wrapBrokerWithPoolingHandle(pbf.createNewBrokerInstance((PBKey) key), pool); | |
253 | } | |
254 | ||
255 | /** | |
256 | * Do all cleanup stuff here. | |
257 | */ | |
258 | public void destroyObject(Object key, Object obj) throws Exception | |
259 | { | |
260 | PoolablePersistenceBroker pb = (PoolablePersistenceBroker) obj; | |
261 | PersistenceBroker broker = pb.getInnermostDelegate(); | |
262 | if (broker instanceof PersistenceBrokerImpl) | |
263 | { | |
264 | log.info("Destroy PersistenceBroker instance " + obj); | |
265 | ((PersistenceBrokerImpl) broker).destroy(); | |
266 | } | |
267 | pb.destroy(); | |
268 | } | |
269 | ||
270 | /** | |
271 | * Check if the given PersistenceBroker instance | |
272 | * was already in transaction. | |
273 | * Was called when | |
274 | * {@link PBPoolInfo#init} | |
275 | * method does set <code>testOnBorrow(true)</code>. | |
276 | * (Default was false, thus this method wasn't called) | |
277 | * See documentation jakarta-connons-pool api. | |
278 | */ | |
279 | public boolean validateObject(Object key, Object obj) | |
280 | { | |
281 | // here we could validate the PB instance | |
282 | // if corresponding configuration properties are set | |
283 | if (((PersistenceBroker) obj).isInTransaction()) | |
284 | { | |
285 | log.error("Illegal broker state! This broker instance was already in transaction."); | |
286 | return false; | |
287 | } | |
288 | return true; | |
289 | } | |
290 | ||
291 | /** | |
292 | * Called before borrow object from pool. | |
293 | */ | |
294 | public void activateObject(Object key, Object obj) throws Exception | |
295 | { | |
296 | ((PBState) obj).setClosed(false); | |
297 | } | |
298 | ||
299 | /** | |
300 | * Called before return object to pool. | |
301 | */ | |
302 | public void passivateObject(Object key, Object obj) throws Exception | |
303 | { | |
304 | ((PBState) obj).setClosed(true); | |
305 | } | |
306 | } | |
307 | } |