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