1   /*
2    * $Id: PooledJavaComponentTestCase.java 11433 2008-03-20 03:43:57Z dirk.olmes $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.component;
12  
13  import org.mule.api.component.LifecycleAdapter;
14  import org.mule.config.PoolingProfile;
15  import org.mule.object.PrototypeObjectFactory;
16  import org.mule.tck.services.UniqueComponent;
17  import org.mule.tck.testmodels.fruit.Orange;
18  import org.mule.tck.testmodels.fruit.WaterMelon;
19  import org.mule.util.ExceptionUtils;
20  
21  public class PooledJavaComponentTestCase extends AbstractComponentTestCase
22  {
23  
24      public static final byte MAX_ACTIVE = 3;
25      public static final long MAX_WAIT = 1500;
26  
27      protected PoolingProfile getDefaultPoolingProfile()
28      {
29          PoolingProfile pp = new PoolingProfile();
30          pp.setExhaustedAction(PoolingProfile.WHEN_EXHAUSTED_FAIL);
31          pp.setMaxActive(MAX_ACTIVE);
32          pp.setMaxWait(MAX_WAIT);
33          pp.setInitialisationPolicy(PoolingProfile.INITIALISE_NONE);
34          return pp;
35      }
36  
37      // @Override
38      protected PrototypeObjectFactory getObjectFactory()
39      {
40          return new PrototypeObjectFactory(Orange.class);
41      }
42  
43      // @Override
44      public void testComponentCreation() throws Exception
45      {
46          PrototypeObjectFactory objectFactory = getObjectFactory();
47          objectFactory.setObjectClass(Orange.class);
48          objectFactory.initialise();
49  
50          PoolingProfile pp = getDefaultPoolingProfile();
51          pp.setExhaustedAction(PoolingProfile.WHEN_EXHAUSTED_FAIL);
52  
53          PooledJavaComponent component = new PooledJavaComponent(objectFactory, pp);
54          assertNotNull(component.getObjectFactory());
55          assertEquals(objectFactory, component.getObjectFactory());
56          assertEquals(Orange.class, component.getObjectFactory().getObjectClass());
57          assertEquals(Orange.class, component.getObjectType());
58          assertNotNull(component.getPoolingProfile());
59          assertEquals(pp, component.getPoolingProfile());
60          assertEquals(PoolingProfile.WHEN_EXHAUSTED_FAIL, component.getPoolingProfile().getExhaustedAction());
61      }
62  
63      public void testPoolCreation() throws Exception
64      {
65          PooledJavaComponent component = new PooledJavaComponent(getObjectFactory(), getDefaultPoolingProfile());
66          assertNull(component.lifecycleAdapterPool);
67          component.setService(getTestService());
68          component.initialise();
69          assertNull(component.lifecycleAdapterPool);
70          component.start();
71          assertNotNull(component.lifecycleAdapterPool);
72          component.stop();
73          assertNull(component.lifecycleAdapterPool);
74      }
75  
76      // @Override
77      public void test() throws Exception
78      {
79          PooledJavaComponent component = new PooledJavaComponent(getObjectFactory(), getDefaultPoolingProfile());
80          component.setService(getTestService());
81          component.initialise();
82          component.start();
83          assertNotSame(component.borrowComponentLifecycleAdaptor(), component.borrowComponentLifecycleAdaptor());
84          component.stop();
85          component.start();
86          assertNotSame(((DefaultLifecycleAdapter) component.borrowComponentLifecycleAdaptor()).componentObject,
87              ((DefaultLifecycleAdapter) component.borrowComponentLifecycleAdaptor()).componentObject);
88      }
89  
90      public void testCreatePool() throws Exception
91      {
92          PooledJavaComponent component = new PooledJavaComponent(getObjectFactory(), getDefaultPoolingProfile());
93          component.setService(getTestService());
94          component.initialise();
95          component.start();
96  
97          assertEquals(0, component.lifecycleAdapterPool.getNumActive());
98  
99          LifecycleAdapter borrowed = component.borrowComponentLifecycleAdaptor();
100         assertNotNull(borrowed);
101         assertEquals(1, component.lifecycleAdapterPool.getNumActive());
102         component.returnComponentLifecycleAdaptor(borrowed);
103         assertEquals(0, component.lifecycleAdapterPool.getNumActive());
104 
105         borrowed = component.borrowComponentLifecycleAdaptor();
106         assertNotNull(borrowed);
107         assertEquals(1, component.lifecycleAdapterPool.getNumActive());
108         Object borrowed2 = component.borrowComponentLifecycleAdaptor();
109         assertNotNull(borrowed2);
110         assertEquals(2, component.lifecycleAdapterPool.getNumActive());
111     }
112 
113     public void testFailOnExhaust() throws Exception
114     {
115         PoolingProfile pp = getDefaultPoolingProfile();
116         pp.setExhaustedAction(PoolingProfile.WHEN_EXHAUSTED_WAIT);
117         PooledJavaComponent component = new PooledJavaComponent(getObjectFactory(), pp);
118         component.setService(getTestService());
119         component.initialise();
120         component.start();
121 
122         Object borrowed = null;
123 
124         for (int i = 0; i < MAX_ACTIVE; i++)
125         {
126             borrowed = component.borrowComponentLifecycleAdaptor();
127             assertNotNull(borrowed);
128             assertEquals(component.lifecycleAdapterPool.getNumActive(), i + 1);
129         }
130 
131         try
132         {
133             borrowed = component.borrowComponentLifecycleAdaptor();
134             fail("Should throw an Exception");
135         }
136         catch (Exception e)
137         {
138             // expected
139         }
140     }
141 
142     public void testBlockExpiryOnExhaust() throws Exception
143     {
144         PoolingProfile pp = getDefaultPoolingProfile();
145         pp.setExhaustedAction(PoolingProfile.WHEN_EXHAUSTED_WAIT);
146         PooledJavaComponent component = new PooledJavaComponent(getObjectFactory(), pp);
147         component.setService(getTestService());
148         component.initialise();
149         component.start();
150 
151         Object borrowed = null;
152 
153         assertEquals(0, component.lifecycleAdapterPool.getNumActive());
154         borrowed = component.borrowComponentLifecycleAdaptor();
155         assertNotNull(borrowed);
156         borrowed = component.borrowComponentLifecycleAdaptor();
157         assertNotNull(borrowed);
158         borrowed = component.borrowComponentLifecycleAdaptor();
159         assertNotNull(borrowed);
160         assertEquals(3, component.lifecycleAdapterPool.getNumActive());
161 
162         // TODO
163         // long starttime = System.currentTimeMillis();
164         try
165         {
166             borrowed = component.borrowComponentLifecycleAdaptor();
167             fail("Should throw an Exception");
168         }
169         catch (Exception e)
170         {
171             // TODO
172             // long totalTime = System.currentTimeMillis() - starttime;
173             // Need to allow for alittle variance in system time
174             // This is unreliable
175             // assertTrue(totalTime < (DEFAULT_WAIT + 300) && totalTime >
176             // (DEFAULT_WAIT - 300));
177         }
178     }
179 
180     public void testBlockOnExhaust() throws Exception
181     {
182         PoolingProfile pp = getDefaultPoolingProfile();
183         pp.setExhaustedAction(PoolingProfile.WHEN_EXHAUSTED_WAIT);
184         PooledJavaComponent component = new PooledJavaComponent(getObjectFactory(), pp);
185         component.setService(getTestService());
186         component.initialise();
187         component.start();
188 
189         Object borrowed = null;
190 
191         assertEquals(0, component.lifecycleAdapterPool.getNumActive());
192 
193         borrowed = component.borrowComponentLifecycleAdaptor();
194         borrowed = component.borrowComponentLifecycleAdaptor();
195         assertEquals(2, component.lifecycleAdapterPool.getNumActive());
196 
197         // TODO
198         // long starttime = System.currentTimeMillis();
199         long borrowerWait = 500;
200         Borrower borrower = new Borrower(component, borrowerWait);
201         borrower.start();
202         // Make sure the borrower borrows first
203         try
204         {
205             Thread.sleep(200);
206         }
207         catch (InterruptedException e)
208         {
209             // ignore
210         }
211 
212         borrowed = component.borrowComponentLifecycleAdaptor();
213         // TODO
214         // long totalTime = System.currentTimeMillis() - starttime;
215         // Need to allow for alittle variance in system time
216         // This is unreliable
217         // assertTrue(totalTime < (borrowerWait + 300) && totalTime >
218         // (borrowerWait -300));
219 
220         assertNotNull(borrowed);
221     }
222 
223     public void testGrowOnExhaust() throws Exception
224     {
225         PoolingProfile pp = getDefaultPoolingProfile();
226         pp.setExhaustedAction(PoolingProfile.WHEN_EXHAUSTED_GROW);
227         PooledJavaComponent component = new PooledJavaComponent(getObjectFactory(), pp);
228         component.setService(getTestService());
229         component.initialise();
230         component.start();
231 
232         Object borrowed = component.borrowComponentLifecycleAdaptor();
233         borrowed = component.borrowComponentLifecycleAdaptor();
234         borrowed = component.borrowComponentLifecycleAdaptor();
235         assertEquals(3, component.lifecycleAdapterPool.getNumActive());
236         // assertEquals(3, pool.getMaxSize());
237 
238         // Should now grow
239         borrowed = component.borrowComponentLifecycleAdaptor();
240         assertNotNull(borrowed);
241 
242         assertEquals(4, component.lifecycleAdapterPool.getNumActive());
243     }
244 
245     public void testClearPool() throws Exception
246     {
247         PoolingProfile pp = getDefaultPoolingProfile();
248         pp.setExhaustedAction(PoolingProfile.WHEN_EXHAUSTED_FAIL);
249         PooledJavaComponent component = new PooledJavaComponent(getObjectFactory(), pp);
250         component.setService(getTestService());
251         component.initialise();
252         component.start();
253 
254         LifecycleAdapter borrowed = component.borrowComponentLifecycleAdaptor();
255         assertEquals(1, component.lifecycleAdapterPool.getNumActive());
256         component.returnComponentLifecycleAdaptor(borrowed);
257 
258         component.stop();
259         component.start();
260         assertEquals(0, component.lifecycleAdapterPool.getNumActive());
261     }
262 
263     public void testObjectUniqueness() throws Exception
264     {
265         PoolingProfile pp = getDefaultPoolingProfile();
266         pp.setExhaustedAction(PoolingProfile.WHEN_EXHAUSTED_FAIL);
267         PooledJavaComponent component = new PooledJavaComponent(new PrototypeObjectFactory(UniqueComponent.class), pp);
268         component.setService(getTestService());
269         component.initialise();
270         component.start();
271 
272         assertEquals(0, component.lifecycleAdapterPool.getNumActive());
273 
274         Object obj;
275 
276         obj = ((DefaultLifecycleAdapter) component.borrowComponentLifecycleAdaptor()).componentObject;
277         assertNotNull(obj);
278         assertTrue("Object should be of type UniqueComponent", obj instanceof UniqueComponent);
279         String id1 = ((UniqueComponent) obj).getId();
280         assertNotNull(id1);
281 
282         obj = ((DefaultLifecycleAdapter) component.borrowComponentLifecycleAdaptor()).componentObject;
283         assertNotNull(obj);
284         assertTrue("Object should be of type UniqueComponent", obj instanceof UniqueComponent);
285         String id2 = ((UniqueComponent) obj).getId();
286         assertNotNull(id2);
287 
288         obj = ((DefaultLifecycleAdapter) component.borrowComponentLifecycleAdaptor()).componentObject;
289         assertNotNull(obj);
290         assertTrue("Object should be of type UniqueComponent", obj instanceof UniqueComponent);
291         String id3 = ((UniqueComponent) obj).getId();
292         assertNotNull(id3);
293 
294         assertFalse("Service IDs " + id1 + " and " + id2 + " should be different", id1.equals(id2));
295         assertFalse("Service IDs " + id2 + " and " + id3 + " should be different", id2.equals(id3));
296     }
297 
298     public void testDisposingFactoryDisposesObject() throws Exception
299     {
300         PooledJavaComponent component = new PooledJavaComponent(new PrototypeObjectFactory(WaterMelon.class),
301             getDefaultPoolingProfile());
302         component.setService(getTestService());
303         component.initialise();
304         component.start();
305 
306         DefaultLifecycleAdapter lifecycleAdapter = (DefaultLifecycleAdapter) component.borrowComponentLifecycleAdaptor();
307         component.returnComponentLifecycleAdaptor(lifecycleAdapter);
308         component.dispose();
309 
310         assertEquals("disposed", ((WaterMelon) lifecycleAdapter.componentObject).getState());
311     }
312 
313     public void testLifeCycleMethods() throws Exception
314     {
315         PooledJavaComponent component = new PooledJavaComponent(new PrototypeObjectFactory(WaterMelon.class),
316             getDefaultPoolingProfile());
317         component.setService(getTestService());
318         component.initialise();
319         component.start();
320 
321         Object obj = component.lifecycleAdapterPool.getObjectFactory().getInstance();
322         assertNotNull(obj);
323         // assertTrue(of.validateObject(obj));
324         // of.activateObject(obj);
325         // of.passivateObject(obj);
326         // of.destroyObject(obj);
327     }
328 
329     private class Borrower extends Thread
330     {
331         private PooledJavaComponent component;
332         private long time;
333 
334         public Borrower(PooledJavaComponent component, long time)
335         {
336             super("Borrower");
337             if (component == null)
338             {
339                 throw new IllegalArgumentException("Pool cannot be null");
340             }
341             this.component = component;
342             if (time < 500)
343             {
344                 time = 500;
345             }
346             this.time = time;
347         }
348 
349         public void run()
350         {
351             try
352             {
353                 LifecycleAdapter object = component.borrowComponentLifecycleAdaptor();
354                 try
355                 {
356                     sleep(time);
357                 }
358                 catch (InterruptedException e)
359                 {
360                     // ignore
361                 }
362                 component.returnComponentLifecycleAdaptor(object);
363             }
364             catch (Exception e)
365             {
366                 fail("Borrower thread failed:\n" + ExceptionUtils.getStackTrace(e));
367             }
368         }
369 
370     }
371 
372 }