1 package com.atlassian.config.lifecycle;
2
3 import com.atlassian.config.lifecycle.events.ApplicationStartedEvent;
4 import com.atlassian.config.lifecycle.events.ApplicationStoppedEvent;
5 import com.atlassian.config.lifecycle.events.ApplicationStoppingEvent;
6 import com.atlassian.event.api.EventPublisher;
7 import com.atlassian.johnson.event.Event;
8 import com.atlassian.johnson.event.EventLevel;
9 import com.atlassian.johnson.event.EventType;
10 import com.atlassian.plugin.PluginAccessor;
11 import org.slf4j.Logger;
12 import org.slf4j.LoggerFactory;
13
14 import javax.servlet.ServletContext;
15 import java.util.Collections;
16 import java.util.List;
17
18 import static com.google.common.collect.Lists.newArrayList;
19
20 public class DefaultLifecycleManager implements LifecycleManager
21 {
22 private static final Logger log = LoggerFactory.getLogger(LifecycleManager.class);
23
24 private PluginAccessor pluginAccessor;
25 private EventPublisher eventPublisher;
26 private boolean startedUp;
27
28 public void startUp(ServletContext servletContext)
29 {
30 final List<LifecyclePluginModuleDescriptor> moduleDescriptors = getLifecyclePluginModuleDescriptors();
31 final LifecycleContext context = new DefaultLifecycleContext(servletContext);
32
33 LifecyclePluginModuleDescriptor currentDescriptor = null;
34 try
35 {
36 for (LifecyclePluginModuleDescriptor descriptor : moduleDescriptors)
37 {
38 currentDescriptor = descriptor;
39 log.info("Starting: " + descriptor);
40 ((LifecycleItem) descriptor.getModule()).startup(context);
41 }
42
43 eventPublisher.publish(new ApplicationStartedEvent(this));
44 startedUp = true;
45 }
46 catch (Throwable t)
47 {
48 panicAndShutdown(t, context, currentDescriptor);
49 }
50 }
51
52 public void shutDown(ServletContext servletContext)
53 {
54 shutDown(servletContext, null);
55 }
56
57 public boolean isStartedUp()
58 {
59 return startedUp;
60 }
61
62 private void panicAndShutdown(Throwable t, LifecycleContext context, LifecyclePluginModuleDescriptor descriptor)
63 {
64 final String errorString = "Unable to start up Confluence. Fatal error during startup sequence: " + descriptor + " - " + t;
65 log.error(errorString, t);
66 context.getAgentJohnson().addEvent(new Event(EventType.get("startup"), errorString, EventLevel.FATAL));
67 shutDown(context.getServletContext(), descriptor.getCompleteKey());
68 }
69
70 private void shutDown(ServletContext servletContext, String startingPluginKey)
71 {
72 eventPublisher.publish(new ApplicationStoppingEvent(this));
73
74 final List<LifecyclePluginModuleDescriptor> moduleDescriptors = getLifecyclePluginModuleDescriptors();
75 Collections.reverse(moduleDescriptors);
76 final LifecycleContext context = new DefaultLifecycleContext(servletContext);
77
78 boolean started = startingPluginKey == null;
79
80 for (LifecyclePluginModuleDescriptor descriptor : moduleDescriptors)
81 {
82 if (!started)
83 {
84 if (descriptor.getCompleteKey().equals(startingPluginKey))
85 {
86 started = true;
87 }
88 else
89 {
90 continue;
91 }
92 }
93
94 log.info("Shutting down: " + descriptor);
95 final LifecycleItem item = (LifecycleItem) descriptor.getModule();
96 try
97 {
98 item.shutdown(context);
99 }
100 catch (Throwable t)
101 {
102 log.error("Error running shutdown plugin: " + descriptor.getDescription() + " - " + t, t);
103 }
104 }
105
106 eventPublisher.publish(new ApplicationStoppedEvent(this));
107 }
108
109 private List<LifecyclePluginModuleDescriptor> getLifecyclePluginModuleDescriptors()
110 {
111 final List<LifecyclePluginModuleDescriptor> modules = newArrayList(
112 pluginAccessor.getEnabledModuleDescriptorsByClass(LifecyclePluginModuleDescriptor.class));
113 Collections.sort(modules);
114 return modules;
115 }
116
117 public void setPluginAccessor(PluginAccessor pluginAccessor)
118 {
119 this.pluginAccessor = pluginAccessor;
120 }
121
122 public void setEventPublisher(EventPublisher eventPublisher)
123 {
124 this.eventPublisher = eventPublisher;
125 }
126 }