View Javadoc

1   package org.appfuse.webapp.listener;
2   
3   import org.apache.commons.logging.Log;
4   import org.apache.commons.logging.LogFactory;
5   import org.appfuse.Constants;
6   import org.appfuse.service.GenericManager;
7   import org.appfuse.service.LookupManager;
8   import org.springframework.beans.factory.NoSuchBeanDefinitionException;
9   import org.springframework.context.ApplicationContext;
10  import org.springframework.security.authentication.AuthenticationProvider;
11  import org.springframework.security.authentication.ProviderManager;
12  import org.springframework.security.authentication.RememberMeAuthenticationProvider;
13  
14  import org.springframework.security.crypto.password.PasswordEncoder;
15  import org.springframework.web.context.support.WebApplicationContextUtils;
16  
17  import javax.servlet.ServletContext;
18  import javax.servlet.ServletContextEvent;
19  import javax.servlet.ServletContextListener;
20  import java.io.IOException;
21  import java.io.InputStream;
22  import java.util.HashMap;
23  import java.util.Map;
24  import java.util.Random;
25  import java.util.jar.Attributes;
26  import java.util.jar.Manifest;
27  
28  /**
29   * <p>StartupListener class used to initialize and database settings
30   * and populate any application-wide drop-downs.
31   * <p/>
32   * <p>Keep in mind that this listener is executed outside of OpenSessionInViewFilter,
33   * so if you're using Hibernate you'll have to explicitly initialize all loaded data at the
34   * GenericDao or service level to avoid LazyInitializationException. Hibernate.initialize() works
35   * well for doing this.
36   *
37   * @author <a href="mailto:matt@raibledesigns.com">Matt Raible</a>
38   */
39  public class StartupListener implements ServletContextListener {
40      private static final Log log = LogFactory.getLog(StartupListener.class);
41  
42      /**
43       * {@inheritDoc}
44       */
45      @SuppressWarnings("unchecked")
46      public void contextInitialized(ServletContextEvent event) {
47          log.debug("Initializing context...");
48  
49          ServletContext context = event.getServletContext();
50  
51          // Orion starts Servlets before Listeners, so check if the config
52          // object already exists
53          Map<String, Object> config = (HashMap<String, Object>) context.getAttribute(Constants.CONFIG);
54  
55          if (config == null) {
56              config = new HashMap<>();
57          }
58  
59          ApplicationContext ctx =
60                  WebApplicationContextUtils.getRequiredWebApplicationContext(context);
61  
62          PasswordEncoder passwordEncoder = null;
63          try {
64              ProviderManager provider = (ProviderManager) ctx.getBean("org.springframework.security.authentication.ProviderManager#0");
65              for (Object o : provider.getProviders()) {
66                  AuthenticationProvider p = (AuthenticationProvider) o;
67                  if (p instanceof RememberMeAuthenticationProvider) {
68                      config.put("rememberMeEnabled", Boolean.TRUE);
69                  } else if (ctx.getBean("passwordEncoder") != null) {
70                      passwordEncoder = (PasswordEncoder) ctx.getBean("passwordEncoder");
71                  }
72              }
73          } catch (NoSuchBeanDefinitionException n) {
74              log.debug("authenticationManager bean not found, assuming test and ignoring...");
75              // ignore, should only happen when testing
76          }
77  
78          context.setAttribute(Constants.CONFIG, config);
79  
80          // output the retrieved values for the Init and Context Parameters
81          if (log.isDebugEnabled()) {
82              log.debug("Remember Me Enabled? " + config.get("rememberMeEnabled"));
83              if (passwordEncoder != null) {
84                  log.debug("Password Encoder: " + passwordEncoder.getClass().getSimpleName());
85              }
86              log.debug("Populating drop-downs...");
87          }
88  
89          setupContext(context);
90  
91          // Determine version number for CSS and JS Assets
92          String appVersion = null;
93          try {
94              InputStream is = context.getResourceAsStream("/META-INF/MANIFEST.MF");
95              if (is == null) {
96                  log.warn("META-INF/MANIFEST.MF not found.");
97              } else {
98                  Manifest mf = new Manifest();
99                  mf.read(is);
100                 Attributes atts = mf.getMainAttributes();
101                 appVersion = atts.getValue("Implementation-Version");
102             }
103         } catch (IOException e) {
104             log.error("I/O Exception reading manifest: " + e.getMessage());
105         }
106 
107         // If there was a build number defined in the war, then use it for
108         // the cache buster. Otherwise, assume we are in development mode
109         // and use a random cache buster so developers don't have to clear
110         // their browser cache.
111         if (appVersion == null || appVersion.contains("SNAPSHOT")) {
112             appVersion = "" + new Random().nextInt(100000);
113         }
114 
115         log.info("Application version set to: " + appVersion);
116         context.setAttribute(Constants.ASSETS_VERSION, appVersion);
117     }
118 
119     /**
120      * This method uses the LookupManager to lookup available roles from the data layer.
121      *
122      * @param context The servlet context
123      */
124     public static void setupContext(ServletContext context) {
125         ApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(context);
126         LookupManager mgr = (LookupManager) ctx.getBean("lookupManager");
127 
128         // get list of possible roles
129         context.setAttribute(Constants.AVAILABLE_ROLES, mgr.getAllRoles());
130         log.debug("Drop-down initialization complete [OK]");
131 
132         // Any manager extending GenericManager will do:
133         GenericManager manager = (GenericManager) ctx.getBean("userManager");
134         doReindexing(manager);
135         log.debug("Full text search reindexing complete [OK]");
136     }
137 
138     private static void doReindexing(GenericManager manager) {
139         manager.reindexAll(false);
140     }
141 
142     /**
143      * Shutdown servlet context (currently a no-op method).
144      *
145      * @param servletContextEvent The servlet context event
146      */
147     public void contextDestroyed(ServletContextEvent servletContextEvent) {
148         //LogFactory.release(Thread.currentThread().getContextClassLoader());
149         //Commented out the above call to avoid warning when SLF4J in classpath.
150         //WARN: The method class org.apache.commons.logging.impl.SLF4JLogFactory#release() was invoked.
151         //WARN: Please see http://www.slf4j.org/codes.html for an explanation.
152     }
153 }