Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
ApplicationInitializeListener |
|
| 5.0;5 |
1 | /* | |
2 | * Copyright 2005-2007 The Kuali Foundation | |
3 | * | |
4 | * | |
5 | * Licensed under the Educational Community 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.opensource.org/licenses/ecl2.php | |
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 | package org.kuali.rice.kew.web; | |
18 | ||
19 | import java.io.File; | |
20 | import java.util.ArrayList; | |
21 | import java.util.List; | |
22 | import java.util.Properties; | |
23 | ||
24 | import javax.servlet.ServletContext; | |
25 | import javax.servlet.ServletContextEvent; | |
26 | import javax.servlet.ServletContextListener; | |
27 | ||
28 | import org.apache.commons.lang.StringUtils; | |
29 | import org.apache.log4j.Logger; | |
30 | import org.kuali.rice.core.config.Config; | |
31 | import org.kuali.rice.core.config.ConfigContext; | |
32 | import org.kuali.rice.core.config.JAXBConfigImpl; | |
33 | import org.kuali.rice.core.config.SimpleConfig; | |
34 | import org.kuali.rice.core.util.JSTLConstants; | |
35 | import org.kuali.rice.kew.exception.WorkflowRuntimeException; | |
36 | import org.kuali.rice.kew.util.KEWConstants; | |
37 | import org.kuali.rice.ksb.messaging.MessageFetcher; | |
38 | import org.kuali.rice.ksb.service.KSBServiceLocator; | |
39 | import org.springframework.context.ConfigurableApplicationContext; | |
40 | import org.springframework.context.support.ClassPathXmlApplicationContext; | |
41 | ||
42 | ||
43 | /** | |
44 | * A ServletContextListener responsible for boostrapping the core workflow | |
45 | * engine lifecycle. The environment Map provided to the CoreLifecycle is | |
46 | * derived directly from the ServletContext init parameters. | |
47 | */ | |
48 | 0 | public class ApplicationInitializeListener implements ServletContextListener { |
49 | private static final long serialVersionUID = -6603009920502691099L; | |
50 | ||
51 | 0 | private static final Logger LOG = Logger.getLogger(ApplicationInitializeListener.class); |
52 | ||
53 | // private static final String DEFAULT_LOG4J_CONFIG = "kew-default-log4j.properties"; | |
54 | ||
55 | //private List<Lifecycle> lifeCycles = new LinkedList<Lifecycle>(); | |
56 | 0 | private ConfigurableApplicationContext context = null; |
57 | ||
58 | /** | |
59 | * ServletContextListener interface implementation that schedules the start | |
60 | * of the lifecycle | |
61 | */ | |
62 | public void contextInitialized(ServletContextEvent sce) { | |
63 | // try { | |
64 | // Properties p = new Properties(); | |
65 | // p.load(getClass().getClassLoader().getResourceAsStream(DEFAULT_LOG4J_CONFIG)); | |
66 | // PropertyConfigurator.configure(p); | |
67 | // } catch (Exception e) { | |
68 | // throw new WorkflowRuntimeException(e); | |
69 | // } | |
70 | ||
71 | 0 | LOG.info("Initializing Workflow..."); |
72 | ||
73 | 0 | sce.getServletContext().setAttribute("Constants", new JSTLConstants(KEWConstants.class)); |
74 | ||
75 | 0 | List<String> configLocations = new ArrayList<String>(); |
76 | // use the system prop as an override of the default packaged | |
77 | // META-INF/workflow.xml | |
78 | // String altCoreConfigLocation = System.getProperty(KEWConstants.DEFAULT_CONFIG_LOCATION_PARAM); | |
79 | // if (altCoreConfigLocation != null) { | |
80 | // configLocations.add(altCoreConfigLocation); | |
81 | // } else { | |
82 | // addDefaultConfigLocation(sce.getServletContext(), configLocations); | |
83 | // } | |
84 | // | |
85 | // // use the system property to add additional configurations (useful for | |
86 | // // testing) | |
87 | 0 | String additionalConfigLocations = System.getProperty(KEWConstants.ADDITIONAL_CONFIG_LOCATIONS_PARAM); |
88 | 0 | if (!StringUtils.isBlank(additionalConfigLocations)) { |
89 | 0 | String[] additionalConfigLocationArray = additionalConfigLocations.split(","); |
90 | 0 | for (String additionalConfigLocation : additionalConfigLocationArray) { |
91 | 0 | configLocations.add(additionalConfigLocation); |
92 | } | |
93 | } | |
94 | ||
95 | 0 | String bootstrapSpringBeans = "classpath:org/kuali/rice/kew/config/ServerKEWSpringBeans.xml"; |
96 | 0 | if (!StringUtils.isBlank(System.getProperty(KEWConstants.BOOTSTRAP_SPRING_FILE))) { |
97 | 0 | bootstrapSpringBeans = System.getProperty(KEWConstants.BOOTSTRAP_SPRING_FILE); |
98 | 0 | } else if (!StringUtils.isBlank(sce.getServletContext().getInitParameter(KEWConstants.BOOTSTRAP_SPRING_FILE))) { |
99 | 0 | bootstrapSpringBeans = sce.getServletContext().getInitParameter(KEWConstants.BOOTSTRAP_SPRING_FILE); |
100 | 0 | LOG.info("Found bootstrap Spring Beans file defined in servlet context: " + bootstrapSpringBeans); |
101 | } | |
102 | try { | |
103 | 0 | String basePath = findBasePath(sce.getServletContext()); |
104 | 0 | Properties baseProps = new Properties(); |
105 | 0 | baseProps.putAll(System.getProperties()); |
106 | 0 | baseProps.setProperty("workflow.base", basePath); |
107 | // HACK: need to determine best way to do this... | |
108 | // if the additional config locations property is empty then we need | |
109 | // to explicitly set it so that if we use it in a root config | |
110 | // a value (an empty value) can be found, and the config parser | |
111 | // won't blow up because "additional.config.locations" property | |
112 | // cannot be resolved | |
113 | // An alternative to doing this at the application/module level would | |
114 | // be to push this functionality down into the Rice ConfigFactoryBean | |
115 | // e.g., by writing a simple ResourceFactoryBean that would conditionally | |
116 | // expose the resource, and then plugging the Resource into the ConfigFactoryBean | |
117 | // However, currently, the ConfigFactoryBean operates on String locations, not | |
118 | // Resources. Spring can coerce string <value>s into Resources, but not vice-versa | |
119 | 0 | if (StringUtils.isEmpty(additionalConfigLocations)) { |
120 | 0 | baseProps.setProperty(KEWConstants.ADDITIONAL_CONFIG_LOCATIONS_PARAM, ""); |
121 | } | |
122 | 0 | Config config = new JAXBConfigImpl(baseProps); |
123 | 0 | config.parseConfig(); |
124 | 0 | ConfigContext.init(config); |
125 | ||
126 | 0 | context = new ClassPathXmlApplicationContext(bootstrapSpringBeans); |
127 | 0 | context.start(); |
128 | ||
129 | 0 | MessageFetcher messageFetcher = new MessageFetcher((Integer)null); |
130 | 0 | KSBServiceLocator.getThreadPool().execute(messageFetcher); |
131 | 0 | } catch (Exception e) { |
132 | 0 | e.printStackTrace(); |
133 | 0 | throw new RuntimeException("Workflow failed to start properly. Exiting.", e); |
134 | 0 | } |
135 | 0 | } |
136 | ||
137 | protected String findBasePath(ServletContext servletContext) { | |
138 | 0 | String realPath = servletContext.getRealPath("/"); |
139 | // if cannot obtain real path (because, e.g., deployed as WAR | |
140 | // try a reasonable guess | |
141 | 0 | if (realPath == null) { |
142 | 0 | if (System.getProperty("catalina.base") != null) { |
143 | 0 | realPath = System.getProperty("catalina.base"); |
144 | } else { | |
145 | 0 | realPath = "."; |
146 | } | |
147 | } | |
148 | 0 | String basePath = new File(realPath).getAbsolutePath(); |
149 | // append a trailing path separator to make relatives paths work in conjunction | |
150 | // with empty ("current working directory") basePath | |
151 | 0 | if (basePath.length() > 0 && !basePath.endsWith(File.separator)) { |
152 | 0 | basePath += File.separator; |
153 | } | |
154 | 0 | return basePath; |
155 | } | |
156 | ||
157 | /** | |
158 | * Configures the default config location by first checking the init params | |
159 | * for default locations and then falling back to the standard default | |
160 | * config location. | |
161 | */ | |
162 | protected void addDefaultConfigLocation(ServletContext context, List<String> configLocations) { | |
163 | 0 | String defaultConfigLocation = context.getInitParameter(KEWConstants.DEFAULT_CONFIG_LOCATION_PARAM); |
164 | 0 | if (!StringUtils.isEmpty(defaultConfigLocation)) { |
165 | 0 | String[] locations = defaultConfigLocation.split(","); |
166 | 0 | for (String location : locations) { |
167 | 0 | configLocations.add(location); |
168 | } | |
169 | 0 | } else { |
170 | 0 | configLocations.add(KEWConstants.DEFAULT_SERVER_CONFIG_LOCATION); |
171 | } | |
172 | 0 | } |
173 | ||
174 | // public void configureLifeCycles() { | |
175 | // lifeCycles.add(new Log4jLifeCycle()); | |
176 | // String springLocation = ConfigContext.getCurrentContextConfig().getAlternateSpringFile(); | |
177 | // if (springLocation == null) { | |
178 | // springLocation = "ServerSpring.xml"; | |
179 | // } | |
180 | // lifeCycles.add(new SpringLifeCycle(springLocation)); | |
181 | // lifeCycles.add(new WebApplicationGlobalResourceLifecycle()); | |
182 | // lifeCycles.add(new ServiceDelegatingLifecycle(KEWServiceLocator.THREAD_POOL)); | |
183 | // lifeCycles.add(new ServiceDelegatingLifecycle(KEWServiceLocator.CACHE_ADMINISTRATOR)); | |
184 | // lifeCycles.add(new ServiceDelegatingLifecycle(KEWServiceLocator.SERVICE_REGISTRY)); | |
185 | // lifeCycles.add(new XmlPipelineLifeCycle()); | |
186 | // lifeCycles.add(new EmailReminderLifecycle()); | |
187 | // } | |
188 | ||
189 | public void contextDestroyed(ServletContextEvent sce) { | |
190 | 0 | LOG.info("Shutting down workflow."); |
191 | ||
192 | // Lifecycle lifeCycle; | |
193 | // //stop them in the opposite order they were started... | |
194 | // while(! lifeCycles.isEmpty()) { | |
195 | // lifeCycle = (Lifecycle) ((LinkedList)lifeCycles).removeLast(); | |
196 | // try { | |
197 | // lifeCycle.stop(); | |
198 | // } catch (Exception e) { | |
199 | // LOG.error("Problems shutting down lifecycle " + lifeCycle.getClass().getName(), e); | |
200 | // } | |
201 | // | |
202 | // } | |
203 | try { | |
204 | 0 | if (context != null) { |
205 | 0 | context.close(); |
206 | } | |
207 | 0 | } catch (Exception e) { |
208 | 0 | throw new WorkflowRuntimeException("Failed to shutdown workflow.", e); |
209 | 0 | } |
210 | 0 | } |
211 | ||
212 | } |