| 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 | } |