/Users/lyon/j4p/src/classUtils/pack/util/pool2/ObjectPool.java

1    package classUtils.pack.util.pool2; 
2     
3    import java.io.File; 
4    import java.io.IOException; 
5    import java.io.PrintStream; 
6    import java.lang.reflect.Constructor; 
7    import java.lang.reflect.InvocationTargetException; 
8     
9    import classUtils.pack.util.Setup; 
10   import classUtils.pack.util.pool2.test.ObjectWithID; 
11    
12   /** 
13    * <font color=red>NOT COMPLETE YET</font>. 
14    * <p> 
15    * A pool of object which handles transparent passivation/activation. 
16    * <p> 
17    * This pool create and allocate pooled objects referencing the original objects 
18    * and implementing the same interface(s).  
19    * <p> 
20    * The pool can be used either accessing objects by interface or by class. 
21    * <p> 
22    * The given object class should implement one or more specific interface(s). The instances 
23    * returned by the {@link classUtils.pack.util.pool.ObjectPool#acquire() acquire()} method 
24    * can be directly cast to that interface(s). For example, if a class  
25    * <tt>MyTestObject</tt> implements the <tt>javax.swing.Action</tt> interface, 
26    * the following code can be used: 
27    * <pre> 
28    *  ObjectPool pool = new ObjectPool("test pool", 10, MyTestObject.class); 
29    *  ... 
30    *  Action action = (Action)pool.acquire(); 
31    *  Object obj = action.getValue(); 
32    *  ... 
33    *  action.release(); 
34    *  ... 
35    *  pool.dispose(); 
36    * </pre>  
37    * <p> 
38    * If the given object is used directly as a class (rather than interface), the 
39    * following conditions hold: 
40    * <p> 
41    * <ul> 
42    * <li> The object returned by the pool's {@link classUtils.pack.util.pool.ObjectPool#acquire() acquire()} 
43    *      method cannot be cast to the original class directly, but to the {@link PooledObject 
44    *      PooledObject} interface. 
45    * <li> The returned object implements all the methods of the original object, but since it's 
46    *      type is possibly generated at runtime, the methods are only available trhough reflection. 
47    * <li> The original object can be obtained by invoking {@link PooledObject#_getOriginal() _getOriginal()} 
48    *      on the returned object, and must be released by {@link PooledObject#_getOriginal() _releaseOriginal()}. 
49    * </ul> 
50    * <p> 
51    * For example: 
52    * <pre> 
53    *   ObjectPool pool = new ObjectPool("test pool", 10, MyTestObject.class); 
54    *   ... 
55    *   PooledObject pObj = (PooledObject)pool.acquire(); 
56    *   MyTestObject obj = (MyTestObject)pObj._getOriginal(); 
57    *   obj.myTestMethod(); 
58    *   pObj._releaseOriginal(); 
59    * </pre>. 
60    *    
61    * @version 1.0 
62    * @author Cristiano Sadun 
63    */ 
64   public class ObjectPool extends classUtils.pack.util.pool.ObjectPool { 
65    
66       private String name; 
67       private PrintStream logStream; 
68       private static PrintStream defaultLogStream; 
69       private Configuration configuration; 
70       private BasePassivationManager passivationManager; 
71    
72       /** 
73        * A base class for a factory of {@link BasePassivationManager BasePassivationManager}s. 
74        * It can be extended to produce a specific subclass of {@link BasePassivationManager  
75        * BasePassivationManager}. 
76        */ 
77       protected abstract static class PassivationManagerFactory { 
78           /** 
79            * Return a specific subclass of {@link BasePassivationManager  
80            * BasePassivationManager} implementing a certain passivation 
81            * policy. 
82            *  
83            * @return a concrete subclass of {@link BasePassivationManager  
84            * BasePassivationManager} 
85            */ 
86           protected abstract BasePassivationManager createPassivationThread(); 
87       } 
88    
89       /** 
90        * An {@link ObjectPool.PassivationManagerFactory ObjectPool.PassivationManagerFactory} which 
91        * produces {@link DefaultPassivationManager DefaultPassivationManager}s 
92        */ 
93       public final static class DefaultPassivationManagerFactory 
94           extends PassivationManagerFactory { 
95           /** 
96            * Return the single instance of {@link DefaultPassivationManager DefaultPassivationManager}. 
97            * @return the single instance of {@link DefaultPassivationManager DefaultPassivationManager}. 
98            */ 
99           protected BasePassivationManager createPassivationThread() { 
100              return DefaultPassivationManager.getInstance(); 
101          } 
102      } 
103   
104      /** 
105       * A {@link classUtils.pack.util.pool.ObjectPool.Factory object factory} which produces {@link BasePooledObject BasePooledObject} 
106       * wrappers for other classes. 
107       * <p> 
108       * In detail, this class uses an existing  
109       * {@link classUtils.pack.util.pool.ObjectPool.Factory object factory} 
110       * to produce objects of class C, obtains an appropriate <tt>Pooled<i>C</i></tt> subclass of  
111       * {@link BasePooledObject BasePooledObject} and then wraps the objects in instances of <tt>Pooled<i>C</i></tt>. 
112       */ 
113      protected static class PooledObjectFactory 
114          implements classUtils.pack.util.pool.ObjectPool.Factory { 
115   
116          private Class pooledClass; 
117          private Factory factory; 
118          private Constructor pooledClassConstructor; 
119          private ObjectPool pool; 
120          private static StubClassLoader scl; 
121          private static Object lock = new Object(); 
122   
123          /** 
124           * Create a factory which is used by the given {@link ObjectPool ObjectPool} and employs the given  
125           * {@link classUtils.pack.util.pool.ObjectPool.Factory org.sadun.util.pool.ObjectPool.Factory} 
126           * @param pool the {@link ObjectPool ObjectPool} using this factory to create pooled objects 
127           * @param factory the {@link classUtils.pack.util.pool.ObjectPool.Factory org.sadun.util.pool.ObjectPool.Factory} to produce 
128           *         the original instances 
129           */ 
130          protected PooledObjectFactory(ObjectPool pool, Factory factory) 
131              throws ObjectPoolException { 
132   
133              this.factory = factory; 
134              this.pool = pool; 
135   
136              // Create the stub class loader 
137              createStubClassLoader(); 
138   
139              // Load the pooled class             
140              try { 
141                  pooledClass = 
142                      scl.loadClass( 
143                          scl.getPooledClassName(factory.getProducedClass())); 
144   
145                  try { 
146                      pooledClassConstructor = 
147                          pooledClass.getConstructor( 
148                              new Class[] { 
149                                  ObjectPool.class, 
150                                  factory.getProducedClass()}); 
151                  } catch (NoSuchMethodException e) { 
152                      // This shouldn't happen, since the wrapper is generated on purpose... 
153                      throw new RuntimeException( 
154                          "Corrupted class " + pooledClass.getName(), 
155                          e); 
156                  } 
157   
158              } catch (ClassNotFoundException e) { 
159                  throw new ObjectPoolException( 
160                      "Could not generate/load the pooled class for " 
161                          + factory.getProducedClass().getName(), 
162                      e); 
163              } 
164          } 
165   
166          private static void createStubClassLoader() 
167              throws ObjectPoolException { 
168              if (scl == null) 
169                  synchronized (lock) { 
170   
171                      Class cls = BasePooledObject.class; 
172                      try { 
173                          scl = new StubClassLoader(cls); 
174                          scl.setLogStream(getDefaultLogStream()); 
175                      } catch (IOException e) { 
176                          e.printStackTrace(); 
177                          throw new IllegalStateException( 
178                              "Cannot create StubClassLoader using " 
179                                  + cls.getName()); 
180                      } 
181                  } 
182          } 
183   
184          /** 
185           * @see classUtils.pack.util.pool.ObjectPool.Factory#create() 
186           */ 
187          public Object create() throws ObjectPoolException { 
188              // Use the original factory to create the object 
189              try { 
190                  BasePooledObject obj = 
191                      (BasePooledObject) pooledClassConstructor.newInstance( 
192                          new Object[] { null, factory.create()}); 
193                  obj.setObjectPool(pool); 
194                  return obj; 
195              } catch (InstantiationException e) { 
196                  throw new ObjectPoolException( 
197                      "Cannot instantiate pooled object for " 
198                          + factory.getProducedClass().getName(), 
199                      e); 
200              } catch (IllegalAccessException e) { 
201                  throw new ObjectPoolException( 
202                      "Cannot instantiate pooled object for " 
203                          + factory.getProducedClass().getName(), 
204                      e); 
205              } catch (InvocationTargetException e) { 
206                  throw new ObjectPoolException( 
207                      "Cannot instantiate pooled object for " 
208                          + factory.getProducedClass().getName(), 
209                      e); 
210              } 
211   
212          } 
213   
214          /** 
215           * @see classUtils.pack.util.pool.ObjectPool.Factory#getProducedClass() 
216           */ 
217          public Class getProducedClass() { 
218              return pooledClass; 
219          } 
220   
221      } 
222   
223      /** 
224       * Create a named object pool of objects of the given class and 
225       * the given {@link Configuration Configuration} (which also provides 
226       * the size of the pool). 
227       * <p> 
228       * The objects are created by invoking their default constructor. 
229       * @param poolName the name of the pool 
230       * @param configuration a {@link Configuration Configuration} object 
231       * @param objectType the class of objects to create 
232       */ 
233      public ObjectPool( 
234          String poolName, 
235          Configuration configuration, 
236          Class objectType) 
237          throws ObjectPoolException { 
238          this(poolName, configuration, objectType, (Setup) null); 
239      } 
240   
241      /** 
242       * Create a named object pool of objects of the given class and 
243       * the given {@link Configuration Configuration} (which also provides 
244       * the size of the pool). 
245       * <p> 
246       * The objects are created by invoking their default constructor. 
247       * <p> 
248       * After the creation, each object is passed by the given {@link  
249       * org.sadun.util.Setup Setup object}. 
250       *  
251       * @param poolName the name of the pool 
252       * @param configuration a {@link Configuration Configuration} object 
253       * @param objectType the class of objects to create 
254       * @param setupObject the {@link classUtils.pack.util.Setup Setup object} used 
255       *         for post-construction setup 
256       */ 
257      public ObjectPool( 
258          String poolName, 
259          Configuration configuration, 
260          Class objectType, 
261          Setup setupObject) 
262          throws ObjectPoolException { 
263          this(poolName, configuration, objectType, new Object[] { 
264          }, setupObject); 
265      } 
266   
267      /** 
268       * Create a named object pool of objects of the given class and 
269       * the given {@link Configuration Configuration} (which also provides 
270       * the size of the pool). 
271       * <p> 
272       * The objects are created by invoking the constructor matching the types 
273       * of the given parameter objects. 
274       *  
275       * @param poolName the name of the pool 
276       * @param configuration a {@link Configuration Configuration} object 
277       * @param objectType the class of objects to create 
278       * @param params the array of parameters used for constructing the object 
279       */ 
280      public ObjectPool( 
281          String poolName, 
282          Configuration configuration, 
283          Class objectType, 
284          Object[] params) { 
285          this(poolName, configuration, objectType, params, null); 
286      } 
287   
288      /** 
289       * Create a named object pool of objects of the given class and 
290       * the given {@link Configuration Configuration} (which also provides 
291       * the size of the pool). 
292       * <p> 
293       * The objects are created by invoking the constructor matching the types 
294       * of the given parameter objects. 
295       * <p> 
296       * After the creation, each object is passed by the given {@link  
297       * org.sadun.util.Setup Setup object}. 
298       *  
299       * @param poolName the name of the pool 
300       * @param configuration a {@link Configuration Configuration} object 
301       * @param objectType the class of objects to create 
302       * @param params the array of parameters used for constructing the object 
303       * @param setupObject the {@link classUtils.pack.util.Setup Setup object} used 
304       *         for post-construction setup 
305       */ 
306      public ObjectPool( 
307          String poolName, 
308          Configuration configuration, 
309          Class objectType, 
310          Object[] params, 
311          Setup setupObject) 
312          throws ObjectPoolException { 
313          this( 
314              poolName, 
315              configuration, 
316              new ObjectFactory(objectType, params, setupObject)); 
317      } 
318   
319      /** 
320       * Create a named object pool of <tt>n</tt> objects of the given class and 
321       * a default {@link Configuration Configuration}. 
322       * <p> 
323       * The objects are created by invoking the constructor matching the types 
324       * of the given parameter objects. 
325       *  
326       * @param n the number of objects to create 
327       * @param poolName the name of the pool 
328       * @param objectType the class of objects to create 
329       * @param params the array of parameters used for constructing the object 
330       */ 
331      public ObjectPool( 
332          String poolName, 
333          int n, 
334          Class objectType, 
335          Object[] params) { 
336          this(poolName, new Configuration(n), objectType, params); 
337      } 
338   
339      /** 
340       * Create a named object pool of <tt>n</tt> objects of the given class and 
341       * a default {@link Configuration Configuration}. 
342       * <p> 
343       * The objects are created by invoking their default constructor. 
344       *  
345       * @param n the number of objects to create 
346       * @param poolName the name of the pool 
347       * @param objectType the class of objects to create 
348       * @param params the array of parameters used for constructing the object 
349       */ 
350      public ObjectPool(String poolName, int n, Class objectType) { 
351          this(poolName, new Configuration(n), objectType, new Object[0]); 
352      } 
353   
354      /** 
355       * Create a named object pool of objects of the given class and 
356       * the given {@link Configuration Configuration} (which also provides 
357       * the size of the pool). 
358       * <p> 
359       * The objects are created by using the given {@link classUtils.pack.util.pool.ObjectPool.Factory 
360       * object factory}. 
361       * <p> 
362       * @param poolName the name of the pool 
363       * @param configuration a {@link Configuration Configuration} object 
364       * @param factory the {@link classUtils.pack.util.pool.ObjectPool.Factory  object factory} which produces the instances to pool. 
365       */ 
366      public ObjectPool( 
367          String poolName, 
368          Configuration configuration, 
369          Factory factory) 
370          throws ObjectPoolException { 
371          super( 
372              configuration.getPoolSize(), 
373              new PooledObjectFactory(null, factory)); 
374          setPool(createObjectsArray(), this); 
375   
376          this.configuration = configuration; 
377          this.name = poolName; 
378          this.logStream = getDefaultLogStream(); 
379   
380          passivationManager = 
381              configuration 
382                  .getPassivationManagerFactory() 
383                  .createPassivationThread(); 
384          passivationManager.setLogStream(logStream); 
385   
386          passivationManager.addPool(this); 
387   
388          // Initialize 
389          if (logStream != null) 
390              logStream.println( 
391                  "Pool of " 
392                      + getSize() 
393                      + " instances of " 
394                      + factory.getProducedClass() 
395                      + " created."); 
396   
397          passivationManager.start(); 
398      } 
399   
400      /** 
401       * Returns the defaultLogStream. 
402       * @return PrintStream 
403       */ 
404      public static PrintStream getDefaultLogStream() { 
405          return defaultLogStream; 
406      } 
407   
408      /** 
409       * Sets the defaultLogStream. 
410       * @param defaultLogStream The defaultLogStream to set 
411       */ 
412      public static void setDefaultLogStream(PrintStream defaultLogStream) { 
413          ObjectPool.defaultLogStream = defaultLogStream; 
414      } 
415   
416      /** 
417       * Returns the logStream. 
418       * @return PrintStream 
419       */ 
420      public PrintStream getLogStream() { 
421          return logStream; 
422      } 
423   
424      /** 
425       * Sets the logStream. 
426       * @param logStream The logStream to set 
427       */ 
428      public void setLogStream(PrintStream logStream) { 
429          this.logStream = logStream; 
430          PooledObjectFactory.scl.setLogStream(logStream); 
431      } 
432   
433      /** 
434       * Returns the configuration. 
435       * @return Configuration 
436       */ 
437      public Configuration getConfiguration() { 
438          return configuration; 
439      } 
440   
441      Object[] createObjectsArray() { 
442          Object[] pool2 = new Object[pool.length]; 
443          for (int i = 0; i < pool.length; i++) { 
444              pool2[i] = pool[i].getObject(); 
445          } 
446          return pool2; 
447      } 
448   
449      synchronized boolean isAcquired(PooledObject obj) { 
450          //assert(used.contains(obj) || free.contains(obj)); 
451          return used.contains(obj); 
452      } 
453   
454      /** 
455       * A convenience method which already casts the result of {@link classUtils.pack.util.pool.ObjectPool#acquire() acquire()} 
456       * to the {@link PooledObject PooledObject} type. 
457       * @return one object in the pool, obtained invoking {@link classUtils.pack.util.pool.ObjectPool#acquire() acquire()} 
458       */ 
459      public PooledObject acquireInstance() { 
460          return (PooledObject) acquire(); 
461      } 
462   
463      /** 
464       * Returns the name. 
465       * @return String 
466       */ 
467      public String getName() { 
468          return name; 
469      } 
470   
471      public void dispose() { 
472          passivationManager.shutdown(); 
473      } 
474   
475      /** 
476       * Returns the passivationManager. 
477       * @return BasePassivationManager 
478       */ 
479      public BasePassivationManager getPassivationManager() { 
480          return passivationManager; 
481      } 
482   
483      /** 
484       * Method setPool. Set the given pool as the pool refrenced by each BasePooledObject. 
485       * @param objects 
486       * @param objectPool 
487       */ 
488      private void setPool(Object[] objects, ObjectPool objectPool) { 
489          for (int i = 0; i < objects.length; i++) { 
490              ((BasePooledObject) objects[i]).setObjectPool(objectPool); 
491          } 
492      } 
493   
494      /** 
495       * Test method 
496       */ 
497      public static void main(String[] args) throws Exception { 
498          //ObjectPool.setDefaultLogStream(System.out); 
499          DefaultPassivationManager.setDefaultPassivationThreshold(1000L); 
500          ObjectPool pool = 
501              new ObjectPool( 
502                  "Test pool", 
503                  new Configuration(new File(File.separator + "temp"), 10), 
504                  classUtils.pack.util.pool2.test.PassivableObject.class); 
505      //  Thread.sleep(10000); 
506          // Pick an object 
507          ObjectWithID obj = (ObjectWithID) pool.acquire(); 
508          System.out.println("Object ID: "+obj.getId()); 
509          pool.release(obj); 
510      //  Thread.sleep(5000); 
511          pool.dispose(); 
512      } 
513   
514  } 
515