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.context;
8   
9   import org.mule.api.MuleContext;
10  import org.mule.api.MuleException;
11  import org.mule.api.context.MuleContextBuilder;
12  import org.mule.api.context.notification.MuleContextNotificationListener;
13  import org.mule.api.lifecycle.Disposable;
14  import org.mule.api.lifecycle.Initialisable;
15  import org.mule.api.lifecycle.LifecycleException;
16  import org.mule.api.lifecycle.Startable;
17  import org.mule.api.lifecycle.Stoppable;
18  import org.mule.api.security.SecurityManager;
19  import org.mule.config.builders.DefaultsConfigurationBuilder;
20  import org.mule.context.notification.MuleContextNotification;
21  import org.mule.lifecycle.MuleContextLifecycleManager;
22  import org.mule.util.UUID;
23  import org.mule.util.queue.QueueManager;
24  
25  import java.util.ArrayList;
26  import java.util.Arrays;
27  import java.util.List;
28  import java.util.concurrent.atomic.AtomicBoolean;
29  import java.util.concurrent.atomic.AtomicReference;
30  
31  import org.junit.Before;
32  import org.junit.Test;
33  import org.mockito.Mockito;
34  
35  import static org.junit.Assert.assertEquals;
36  import static org.junit.Assert.assertFalse;
37  import static org.junit.Assert.assertNotNull;
38  import static org.junit.Assert.assertSame;
39  import static org.junit.Assert.assertTrue;
40  import static org.mule.tck.MuleAssert.assertTrue;
41  
42  public class MuleContextLifecycleTestCase 
43  {
44      private MuleContextBuilder ctxBuilder;
45      private SensingLifecycleManager lifecycleManager;
46      
47      @Before
48      public void setup() throws Exception
49      {
50          ctxBuilder = new DefaultMuleContextBuilder();
51          lifecycleManager = new SensingLifecycleManager();
52          ctxBuilder.setLifecycleManager(lifecycleManager);
53      }
54      
55      //
56      // Initialize
57      //
58      @Test
59      public void initaliseSuccessful() throws Exception
60      {
61          MuleContext ctx = ctxBuilder.buildMuleContext();
62          assertFalse(ctx.isInitialised());
63          assertFalse(ctx.isInitialising());
64          assertFalse(ctx.isStarted());
65          assertFalse(ctx.isDisposed());
66          assertFalse(ctx.isDisposing());
67  
68          ctx.initialise();
69          assertTrue(ctx.isInitialised());
70          assertFalse(ctx.isInitialising());
71          assertFalse(ctx.isStarted());
72          assertFalse(ctx.isDisposed());
73          assertFalse(ctx.isDisposing());
74      }
75  
76      @Test(expected=IllegalStateException.class)
77      public void initialiseOnInitialised() throws MuleException
78      {
79          MuleContext ctx = ctxBuilder.buildMuleContext();
80          ctx.initialise();
81  
82          // Can't call twice
83          ctx.initialise();
84      }
85      
86      @Test(expected=IllegalStateException.class)
87      public void initialiseOnStarted() throws Exception
88      {
89          MuleContext ctx = ctxBuilder.buildMuleContext();
90          ctx.initialise();
91          new DefaultsConfigurationBuilder().configure(ctx);
92          ctx.start();
93  
94          // Attempt to initialise once started should fail!
95          ctx.initialise();
96      }
97  
98      @Test(expected=IllegalStateException.class)
99      public void initialiseOnStopped() throws Exception
100     {
101         MuleContext ctx = ctxBuilder.buildMuleContext();
102         ctx.initialise();
103         new DefaultsConfigurationBuilder().configure(ctx);
104         ctx.start();
105         ctx.stop();
106         
107         // Attempt to initialise once stopped should fail!
108         ctx.initialise();
109     }
110 
111     @Test(expected=IllegalStateException.class)
112     public void initialiseOnDisposed() throws Exception
113     {
114         MuleContext ctx = ctxBuilder.buildMuleContext();
115         ctx.initialise();
116         new DefaultsConfigurationBuilder().configure(ctx);
117         ctx.start();
118         ctx.stop();
119         ctx.dispose();
120 
121         // Attempt to initialise once disposed should fail!
122         ctx.initialise();
123     }
124 
125     //
126     // Start
127     //    
128     @Test(expected=IllegalStateException.class)
129     public void startBeforeInitialise() throws Exception
130     {
131         MuleContext ctx = ctxBuilder.buildMuleContext();
132         ctx.start();
133     }
134     
135     @Test
136     public void startOnInitialised() throws Exception
137     {
138         MuleContext ctx = ctxBuilder.buildMuleContext();
139         ctx.initialise();
140         
141         new DefaultsConfigurationBuilder().configure(ctx);
142         NotificationListener listener = new NotificationListener();
143         ctx.registerListener(listener);
144         ctx.start();
145         
146         assertTrue(ctx.isInitialised());
147         assertFalse(ctx.isInitialising());
148         assertTrue(ctx.isStarted());
149         assertFalse(ctx.isDisposed());
150         assertFalse(ctx.isDisposing());
151 
152         assertTrue("CONTEXT_STARTING notification never fired", listener.startingNotificationFired);
153         assertTrue("CONTEXT_STARTED notification never fired", listener.startedNotificationFired);
154     }
155 
156     @Test(expected=IllegalStateException.class)
157     public void startOnStarted() throws Exception
158     {
159         MuleContext ctx = ctxBuilder.buildMuleContext();
160         ctx.initialise();
161         
162         new DefaultsConfigurationBuilder().configure(ctx);
163         NotificationListener listener = new NotificationListener();
164         ctx.registerListener(listener);
165         ctx.start();
166 
167         assertTrue("CONTEXT_STARTING notification never fired", listener.startingNotificationFired);
168         assertTrue("CONTEXT_STARTED notification never fired", listener.startedNotificationFired);
169         
170         // Can't call twice
171         ctx.start();
172     }
173 
174     @Test
175     public void startOnStopped() throws Exception
176     {
177         MuleContext ctx = ctxBuilder.buildMuleContext();
178         ctx.initialise();
179         new DefaultsConfigurationBuilder().configure(ctx);
180         ctx.start();
181 
182         ctx.stop();
183         ctx.start();
184         assertTrue(ctx.isInitialised());
185         assertFalse(ctx.isInitialising());
186         assertTrue(ctx.isStarted());
187         assertFalse(ctx.isDisposed());
188         assertFalse(ctx.isDisposing());
189     }
190 
191     @Test(expected=IllegalStateException.class)
192     public void startOnDisposed() throws Exception
193     {
194         MuleContext ctx = ctxBuilder.buildMuleContext();
195         ctx.initialise();
196         ctx.dispose();
197         
198         // Attempt to start once disposed should fail!
199         ctx.start();
200     }
201     
202     //
203     // Stop
204     //
205     @Test(expected=IllegalStateException.class)
206     public void stopBeforeInitialise() throws Exception
207     {
208         MuleContext ctx = ctxBuilder.buildMuleContext();
209 
210         // Attempt to stop before initialise should fail!
211         ctx.stop();
212     }
213  
214     @Test(expected=IllegalStateException.class)
215     public void stopOnInitialised() throws Exception
216     {
217         MuleContext ctx = ctxBuilder.buildMuleContext();
218         ctx.initialise();
219         
220         // cannot stop if not started
221         ctx.stop();
222     }
223     
224     @Test
225     public void stopOnStarted() throws Exception
226     {
227         MuleContext ctx = buildStartedMuleContext();
228         
229         ctx.stop();
230         assertTrue(ctx.isInitialised());
231         assertFalse(ctx.isInitialising());
232         assertFalse(ctx.isStarted());
233         assertFalse(ctx.isDisposed());
234         assertFalse(ctx.isDisposing());
235     }
236     
237     @Test(expected=IllegalStateException.class)
238     public void stopOnStopped() throws Exception
239     {
240         MuleContext ctx = buildStartedMuleContext();
241         ctx.stop();
242         
243         // Can't call twice
244         ctx.stop();
245     }
246     
247     @Test(expected=IllegalStateException.class)
248     public void stopOnDisposed() throws Exception
249     {
250         MuleContext ctx = buildStartedMuleContext();
251         ctx.stop();
252         ctx.dispose();
253         
254         // Attempt to stop once disposed should fail!
255         ctx.stop();
256     }
257 
258     //
259     // Dispose
260     //
261     @Test
262     public void disposeBeforeInitialised()
263     {
264         MuleContext ctx = ctxBuilder.buildMuleContext();
265         ctx.dispose();
266         assertFalse(ctx.isInitialised());
267         assertFalse(ctx.isInitialising());
268         assertFalse(ctx.isStarted());
269         assertTrue(ctx.isDisposed());
270         assertFalse(ctx.isDisposing());
271         
272         assertLifecycleManagerDidApplyPhases(Disposable.PHASE_NAME);
273     }
274     
275     @Test
276     public void disposeOnInitialised() throws Exception
277     {
278         MuleContext ctx = ctxBuilder.buildMuleContext();
279         ctx.initialise();
280         ctx.dispose();
281         assertFalse(ctx.isInitialised());
282         assertFalse(ctx.isInitialising());
283         assertFalse(ctx.isStarted());
284         assertTrue(ctx.isDisposed());
285         assertFalse(ctx.isDisposing());
286         
287         assertLifecycleManagerDidApplyPhases(Initialisable.PHASE_NAME, Disposable.PHASE_NAME);
288     }
289     
290     @Test
291     public void disposeOnStarted() throws Exception
292     {
293         MuleContext ctx = ctxBuilder.buildMuleContext();
294         ctx.initialise();
295         new DefaultsConfigurationBuilder().configure(ctx);
296         final NotificationListener listener = new NotificationListener();
297         ctx.registerListener(listener);
298 
299         ctx.start();
300         ctx.dispose();
301         assertFalse(ctx.isInitialised());
302         assertFalse(ctx.isInitialising());
303         assertFalse(ctx.isStarted());
304         assertTrue(ctx.isDisposed());
305         assertFalse(ctx.isDisposing());
306 
307         // disposing started must go through stop
308         assertLifecycleManagerDidApplyAllPhases();
309 
310         assertTrue("CONTEXT_STOPPING notification never fired", listener.stoppingNotificationFired.get());
311         assertTrue("CONTEXT_STOPPED notification never fired", listener.stoppedNotificationFired.get());
312     }
313     
314     @Test
315     public void disposeOnStopped() throws Exception
316     {
317         MuleContext  ctx = ctxBuilder.buildMuleContext();
318         ctx.initialise();
319         new DefaultsConfigurationBuilder().configure(ctx);
320         ctx.start();
321         ctx.stop();
322         ctx.dispose();
323         assertFalse(ctx.isInitialised());
324         assertFalse(ctx.isInitialising());
325         assertFalse(ctx.isStarted());
326         assertTrue(ctx.isDisposed());
327         assertFalse(ctx.isDisposing());
328         
329         assertLifecycleManagerDidApplyAllPhases();
330     }
331     
332     @Test(expected=IllegalStateException.class)
333     public void disposeOnDisposed() throws Exception
334     {
335         MuleContext ctx = ctxBuilder.buildMuleContext();
336         ctx.initialise();
337         ctx.dispose();
338         
339         // can't call twice
340         ctx.dispose();
341     }
342 
343     @Test
344     public void notificationHasMuleContextRef() throws Exception
345     {
346         MuleContext ctx = ctxBuilder.buildMuleContext();
347         ctx.initialise();
348         new DefaultsConfigurationBuilder().configure(ctx);
349         
350         final AtomicReference<MuleContext> contextFromNotification = new AtomicReference<MuleContext>();
351         final AtomicReference<String> resourceId = new AtomicReference<String>();
352         MuleContextNotificationListener<MuleContextNotification> listener = 
353             new MuleContextNotificationListener<MuleContextNotification>()
354         {
355             public void onNotification(MuleContextNotification notification)
356             {
357                 contextFromNotification.set(notification.getMuleContext());
358                 resourceId.set(notification.getResourceIdentifier());
359             }
360         };
361         ctx.registerListener(listener);
362         ctx.start();
363 
364         assertNotNull(contextFromNotification.get());
365         assertSame(ctx, contextFromNotification.get());
366         assertEquals(ctx.getConfiguration().getId(), resourceId.get());
367     }
368 
369     private MuleContext buildStartedMuleContext() throws Exception
370     {
371         MuleContext ctx = ctxBuilder.buildMuleContext();
372         ctx.initialise();
373     
374         // DefaultMuleContext refuses to start without these objects in place
375         SecurityManager securityManager = Mockito.mock(SecurityManager.class);
376         ctx.getRegistry().registerObject(UUID.getUUID(), securityManager);
377         
378         QueueManager queueManager = Mockito.mock(QueueManager.class);
379         ctx.getRegistry().registerObject(UUID.getUUID(), queueManager);
380         
381         ctx.start();
382         return ctx;
383     }
384 
385     private void assertLifecycleManagerDidApplyPhases(String... phaseNames)
386     {
387         assertTrue(lifecycleManager.didApplyPhases(phaseNames));
388     }
389     
390     private void assertLifecycleManagerDidApplyAllPhases()
391     {
392         assertLifecycleManagerDidApplyPhases(
393             Initialisable.PHASE_NAME,
394             Startable.PHASE_NAME,
395             Stoppable.PHASE_NAME,
396             Disposable.PHASE_NAME);
397     }
398 
399     private static class SensingLifecycleManager extends MuleContextLifecycleManager
400     {
401         private List<String> appliedLifecyclePhases;
402         
403         public SensingLifecycleManager()
404         {
405             super();
406             appliedLifecyclePhases = new ArrayList<String>();
407         }
408 
409         public boolean didApplyPhases(String... phaseNames)
410         {
411             List<String> expectedPhases = Arrays.asList(phaseNames);
412             return expectedPhases.equals(appliedLifecyclePhases);
413         }
414 
415         @Override
416         public void fireLifecycle(String phase) throws LifecycleException
417         {
418             appliedLifecyclePhases.add(phase);
419             super.fireLifecycle(phase);
420         }
421     }
422     
423     static class NotificationListener implements MuleContextNotificationListener<MuleContextNotification>
424     {
425         final AtomicBoolean startingNotificationFired = new AtomicBoolean(false);
426         final AtomicBoolean startedNotificationFired = new AtomicBoolean(false);
427         final AtomicBoolean stoppingNotificationFired = new AtomicBoolean(false);
428         final AtomicBoolean stoppedNotificationFired = new AtomicBoolean(false);
429 
430         public void onNotification(MuleContextNotification notification)
431         {
432             switch (notification.getAction())
433             {
434                 case MuleContextNotification.CONTEXT_STARTING: 
435                     startingNotificationFired.set(true); 
436                     break;
437                     
438                 case MuleContextNotification.CONTEXT_STARTED: 
439                     startedNotificationFired.set(true); 
440                     break;
441                     
442                 case MuleContextNotification.CONTEXT_STOPPING: 
443                     stoppingNotificationFired.set(true); 
444                     break;
445                     
446                 case MuleContextNotification.CONTEXT_STOPPED: 
447                     stoppedNotificationFired.set(true); 
448                     break;
449             }
450         }
451     }
452 }