KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > blandware > atleap > webapp > listener > StartupListener


1 /*
2  * Copyright 2004 Blandware (http://www.blandware.com)
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package com.blandware.atleap.webapp.listener;
17
18 import com.blandware.atleap.common.Constants;
19 import com.blandware.atleap.common.util.CommonConverter;
20 import com.blandware.atleap.common.util.CurrencyConverter;
21 import com.blandware.atleap.search.SearchManager;
22 import com.blandware.atleap.service.core.BackupManager;
23 import com.blandware.atleap.service.core.ContentLocaleManager;
24 import com.blandware.atleap.service.core.MailTemplateManager;
25 import com.blandware.atleap.webapp.menu.MenuRepository;
26 import com.blandware.atleap.webapp.util.core.ApplicationResources;
27 import com.blandware.atleap.webapp.util.core.GlobalProperties;
28 import com.blandware.atleap.webapp.util.core.LocaleUtil;
29 import com.blandware.atleap.webapp.util.core.MenuUtil;
30 import com.blandware.atleap.persistence.exception.BackupFileAccessException;
31 import org.apache.commons.beanutils.ConvertUtils;
32 import org.apache.commons.beanutils.converters.*;
33 import org.apache.commons.logging.Log;
34 import org.apache.commons.logging.LogFactory;
35 import org.hibernate.FlushMode;
36 import org.hibernate.Session;
37 import org.hibernate.SessionFactory;
38 import org.springframework.context.ApplicationContext;
39 import org.springframework.dao.DataAccessResourceFailureException;
40 import org.springframework.orm.hibernate3.SessionFactoryUtils;
41 import org.springframework.orm.hibernate3.SessionHolder;
42 import org.springframework.transaction.support.TransactionSynchronizationManager;
43 import org.springframework.web.context.ContextLoaderListener;
44 import org.springframework.web.context.WebApplicationContext;
45 import org.springframework.web.context.support.WebApplicationContextUtils;
46
47 import javax.naming.Context JavaDoc;
48 import javax.naming.InitialContext JavaDoc;
49 import javax.servlet.ServletContext JavaDoc;
50 import javax.servlet.ServletContextEvent JavaDoc;
51 import javax.servlet.ServletContextListener JavaDoc;
52 import javax.sql.DataSource JavaDoc;
53 import java.beans.Introspector JavaDoc;
54 import java.lang.reflect.Method JavaDoc;
55 import java.lang.reflect.InvocationTargetException JavaDoc;
56 import java.sql.Driver JavaDoc;
57 import java.sql.DriverManager JavaDoc;
58 import java.util.Date JavaDoc;
59 import java.util.Enumeration JavaDoc;
60 import java.util.HashMap JavaDoc;
61 import java.util.Map JavaDoc;
62
63 /**
64  * <p>StartupListener class used to initialize context
65  * </p>
66  *
67  * @author Matt Raible <a HREF="mailto:matt@raibledesigns.com">&lt;matt@raibledesigns.com&gt;</a>
68  * @author Andrey Grebnev <a HREF="mailto:andrey.grebnev@blandware.com">&lt;andrey.grebnev@blandware.com&gt;</a>
69  * @author Sergey Zubtcovskii <a HREF="mailto:sergey.zubtcovskii@blandware.com">&lt;sergey.zubtcovskii@blandware.com&gt;</a>
70  * @version $Revision: 1.48 $ $Date: 2006/03/25 15:12:50 $
71  * @web.listener
72  */

73 public class StartupListener extends ContextLoaderListener implements ServletContextListener JavaDoc {
74
75     /**
76      * Default name of session factory bean
77      */

78     public static final String JavaDoc DEFAULT_SESSION_FACTORY_BEAN_NAME = "sessionFactory";
79
80     /**
81      * Name of session factory bean
82      */

83     protected String JavaDoc sessionFactoryBeanName = DEFAULT_SESSION_FACTORY_BEAN_NAME;
84
85     /**
86      * Transient log instance for this class
87      */

88     protected transient Log log = LogFactory.getLog(StartupListener.class);
89
90     /**
91      * Struts Menu repository
92      */

93     protected MenuRepository menuRepository = null;
94
95     /**
96      * Servlet context of our application
97      */

98     protected ServletContext JavaDoc servletContext = null;
99
100     /**
101      * Spring Application context
102      */

103     protected ApplicationContext applicationContext = null;
104
105     /**
106      * Hibernate Session factory
107      */

108     protected SessionFactory sessionFactory = null;
109
110     /**
111      * Context path of our application
112      */

113     protected String JavaDoc contextPath = null;
114
115     /**
116      * @see org.springframework.web.context.ContextLoaderListener#contextInitialized(javax.servlet.ServletContextEvent)
117      */

118     public void contextInitialized(ServletContextEvent JavaDoc event) {
119         if ( log.isInfoEnabled() ) {
120             log.info("Initializing context...");
121         }
122
123         // call Spring's context ContextLoaderListener to initialize
124
// all the context files specified in web.xml
125
super.contextInitialized(event);
126
127         servletContext = event.getServletContext();
128         contextPath = servletContext.getInitParameter(Constants.CONTEXT_PATH);
129
130         if ( contextPath == null ) {
131             if ( log.isWarnEnabled() ) {
132                 log.warn("No 'contextPath' context parameter, using '/'");
133             }
134             contextPath = "/";
135         } else if ( !contextPath.startsWith("/") ) {
136             contextPath = "/" + contextPath;
137         }
138
139         String JavaDoc daoType = servletContext.getInitParameter(Constants.DAO_TYPE);
140
141         // if daoType is not specified, use DAO as default
142
if ( daoType == null ) {
143             if ( log.isWarnEnabled() ) {
144                 log.warn("No 'daoType' context parameter, using Hibernate");
145             }
146             daoType = Constants.DAO_TYPE_HIBERNATE;
147         }
148
149         // Orion starts Servlets before Listeners, so check if the config
150
// object already exists
151
Map JavaDoc config = (HashMap JavaDoc) servletContext.getAttribute(Constants.CONFIG);
152
153         if ( config == null ) {
154             config = new HashMap JavaDoc();
155         }
156
157         // Create a config object to hold all the app config values
158
config.put(Constants.DAO_TYPE, daoType);
159         servletContext.setAttribute(Constants.CONFIG, config);
160
161         // output the retrieved values for the Init and Context Parameters
162
if ( log.isDebugEnabled() ) {
163             log.debug("daoType: " + daoType);
164         }
165
166         //opening session
167
sessionFactory = lookupSessionFactory();
168         Session session = null;
169         boolean participate = false;
170         if ( TransactionSynchronizationManager.hasResource(sessionFactory) ) {
171             // do not modify the Session: just set the participate flag
172
participate = true;
173         } else {
174             if ( log.isDebugEnabled() ) {
175                 log.debug("Opening temporary Hibernate session in StartupListener");
176             }
177             session = getSession(sessionFactory);
178             TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));
179         }
180
181         applicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
182
183         //create tables and load initial data if required
184
BackupManager backupManager = (BackupManager)applicationContext.getBean(Constants.BACKUP_MANAGER_BEAN);
185         try {
186             backupManager.restore(null, Boolean.FALSE);
187         } catch (BackupFileAccessException e) {
188             if ( log.isDebugEnabled() ) {
189                 log.error("Cannot create tables and load initial data during startup", e);
190             }
191         }
192
193         // initialize content locales
194
ContentLocaleManager contentLocaleManager = (ContentLocaleManager) applicationContext.getBean(Constants.CONTENT_LOCALE_MANAGER_BEAN);
195         contentLocaleManager.initialize();
196         LocaleUtil.getInstance(servletContext);
197
198         // initialize Struts Menu repository
199
MenuRepository menuRepository = new MenuUtil(servletContext, contextPath).initializeMenuRepository();
200         servletContext.setAttribute(MenuRepository.MENU_REPOSITORY_KEY, menuRepository);
201
202         // synchronize roles in deployment descriptor and in persistent storage
203
// initializeSecurityRoles();
204

205         // synchronize global properties in persistence layer with configuration file
206
GlobalProperties.getInstance(servletContext);
207
208         // create or delete mail templates
209
MailTemplateManager mailTemplateManager = (MailTemplateManager) applicationContext.getBean(Constants.MAIL_TEMPLATE_MANAGER_BEAN);
210         mailTemplateManager.initialize();
211
212         //initialize search manager
213
SearchManager.getInstance(servletContext);
214
215         // initialize application resources
216
ApplicationResources.getInstance(servletContext);
217
218         //closing session
219
if ( !participate ) {
220             TransactionSynchronizationManager.unbindResource(sessionFactory);
221             if ( log.isDebugEnabled() ) {
222                 log.debug("Closing temporary Hibernate session in StartupListener");
223             }
224             closeSession(session, sessionFactory);
225         }
226
227         registerConverters();
228     }
229
230     /**
231      * Registers converters used in application
232      */

233     protected void registerConverters() {
234
235         // Note, that in order to correctly convert date to string and vice versa you need to create instance of CommonConverter
236
// with correct locale - it is done in WebappUtil.copyProperties method, so it is better to use it instead of simple call
237
// to BeanUtils.copyProperties
238
ConvertUtils.register(new CommonConverter(), String JavaDoc.class);
239         ConvertUtils.register(new CommonConverter(), Date JavaDoc.class);
240         ConvertUtils.register(new CurrencyConverter(), Double JavaDoc.class);
241         ConvertUtils.register(new CommonConverter(), Object JavaDoc.class);
242
243         //register standard converters in order to setup default value to null
244
ConvertUtils.register(new BooleanConverter(null), Boolean.TYPE);
245         ConvertUtils.register(new BooleanConverter(null), Boolean JavaDoc.class);
246
247         ConvertUtils.register(new ByteConverter(null), Byte.TYPE);
248         ConvertUtils.register(new ByteConverter(null), Byte JavaDoc.class);
249
250         ConvertUtils.register(new CharacterConverter(null), Character.TYPE);
251         ConvertUtils.register(new CharacterConverter(null), Character JavaDoc.class);
252
253         ConvertUtils.register(new DoubleConverter(null), Double.TYPE);
254         ConvertUtils.register(new DoubleConverter(null), Double JavaDoc.class);
255
256         ConvertUtils.register(new FloatConverter(null), Float.TYPE);
257         ConvertUtils.register(new FloatConverter(null), Float JavaDoc.class);
258
259         ConvertUtils.register(new IntegerConverter(null), Integer.TYPE);
260         ConvertUtils.register(new IntegerConverter(null), Integer JavaDoc.class);
261
262         ConvertUtils.register(new LongConverter(null), Long.TYPE);
263         ConvertUtils.register(new LongConverter(null), Long JavaDoc.class);
264
265         ConvertUtils.register(new ShortConverter(null), Short.TYPE);
266         ConvertUtils.register(new ShortConverter(null), Short JavaDoc.class);
267     }
268
269     /**
270      * @see org.springframework.web.context.ContextLoaderListener#contextDestroyed(javax.servlet.ServletContextEvent)
271      */

272     public void contextDestroyed(ServletContextEvent JavaDoc event) {
273         ServletContext JavaDoc servletContext = event.getServletContext();
274
275         //close hibernate session to make sure
276
try {
277             Session session = SessionFactoryUtils.getSession(sessionFactory, false);
278             closeSession(session, sessionFactory);
279         } catch ( Exception JavaDoc ex ) {
280             //do nothing
281
}
282
283         //close session factory
284
try {
285             sessionFactory.close();
286         } catch ( Exception JavaDoc ex ) {
287             //do nothing
288
}
289         sessionFactory = null;
290
291         // call Spring ContextLoaderListener method
292
super.contextDestroyed(event);
293
294         ConvertUtils.deregister();
295
296         ClassLoader JavaDoc classLoader = Thread.currentThread().getContextClassLoader();
297         if ( classLoader == null ) {
298             classLoader = this.getClass().getClassLoader();
299         }
300
301         //release datasource
302
try {
303             Context environment = (Context) new InitialContext JavaDoc().lookup("java:comp/env");
304             String JavaDoc dataSourceName = servletContext.getInitParameter(Constants.DATASOURCE_NAME);
305             DataSource JavaDoc dataSource = (DataSource JavaDoc) environment.lookup(dataSourceName);
306             Method JavaDoc method = dataSource.getClass().getMethod("close", (Class JavaDoc[]) null);
307             method.invoke(dataSource, (Object JavaDoc[]) null);
308         } catch ( Exception JavaDoc ex ) {
309             //do nothing
310
}
311
312         //release drivers
313
try {
314             for ( Enumeration JavaDoc e = DriverManager.getDrivers(); e.hasMoreElements(); ) {
315                 Driver JavaDoc driver = (Driver JavaDoc) e.nextElement();
316                 if ( driver.getClass().getClassLoader() == classLoader ) {
317                     DriverManager.deregisterDriver(driver);
318                 }
319             }
320         } catch ( Throwable JavaDoc e ) {
321             //do nothing
322
}
323
324         if (servletContext != null) {
325             servletContext.removeAttribute(MenuRepository.MENU_REPOSITORY_KEY);
326         }
327
328         servletContext = null;
329         applicationContext = null;
330         log = null;
331
332         //release commons-logging
333
try {
334             Class JavaDoc c = classLoader.loadClass("org.apache.commons.logging.LogFactory");
335             Method JavaDoc m = c.getMethod("release", new Class JavaDoc[] {ClassLoader JavaDoc.class});
336             m.invoke(null, new Object JavaDoc[] {classLoader});
337         } catch (Exception JavaDoc e) {
338             //In some AS may be used old version of commons-logging
339
}
340
341         //release memory if we use Log4J
342
try {
343             Class JavaDoc clazz = classLoader.loadClass("org.apache.log4j.LogManager");
344             Method JavaDoc method = clazz.getMethod("shutdown", (Class JavaDoc[]) null);
345             method.invoke(null, (Object JavaDoc[]) null);
346         } catch ( Exception JavaDoc ex ) {
347             //do nohing
348
}
349
350         Introspector.flushCaches();
351     }
352
353     /**
354      * Synchronizes security roles in deployment descriptor and persistent storage
355      */

356 /*
357     protected void initializeSecurityRoles() {
358         DescriptorParser parser = new DescriptorParser(servletContext);
359         Map securityRoles = parser.getSecurityRoles();
360         RoleManager roleManager = (RoleManager) applicationContext.getBean(Constants.ROLE_MANAGER_BEAN);
361         Map queryParameters = new HashMap();
362         queryParameters.put("fixed", Boolean.TRUE);
363         QueryInfo queryInfo = new QueryInfo();
364         queryInfo.setQueryParameters(queryParameters);
365         List roles = roleManager.listRoles(queryInfo).asList();
366         Set roleNames = securityRoles.keySet();
367
368         // delete non-existent roles
369         for ( Iterator i = roles.iterator(); i.hasNext(); ) {
370             Role role = (Role) i.next();
371             if ( !roleNames.contains(role.getName()) ) {
372                 try {
373                     roleManager.deleteRole(role.getName());
374                 } catch ( BeanNotFoundException e ) {
375                     // bean not found - normally will never occur
376                     if ( log.isErrorEnabled() ) {
377                         StringWriter sw = new StringWriter();
378                         e.printStackTrace(new PrintWriter(sw));
379                         log.error(sw.toString());
380                     }
381                 }
382             }
383         }
384
385         // create or update roles
386         for ( Iterator i = securityRoles.entrySet().iterator(); i.hasNext(); ) {
387             Map.Entry entry = (Map.Entry) i.next();
388             String roleName = (String) entry.getKey();
389             String description = (String) entry.getValue();
390             Role role = roleManager.retrieveRole(roleName);
391             if ( role == null ) {
392                 role = new Role(roleName, StringUtil.capitalize(roleName));
393                 role.setFixed(Boolean.TRUE);
394                 role.setDescription(description);
395                 try {
396                     roleManager.createRole(role);
397                 } catch ( BeanAlreadyExistsException e ) {
398                     if ( log.isFatalEnabled() ) {
399                         StringWriter sw = new StringWriter();
400                         e.printStackTrace(new PrintWriter(sw));
401                         log.fatal("Failed to create role '" + roleName + "'");
402                         log.fatal(sw.toString());
403                     }
404                 }
405             } else {
406                 role.setDescription(description);
407                 role.setFixed(Boolean.TRUE);
408                 try {
409                     roleManager.updateRole(role);
410                 } catch ( BeanAlreadyExistsException e ) {
411                     if ( log.isFatalEnabled() ) {
412                         StringWriter sw = new StringWriter();
413                         e.printStackTrace(new PrintWriter(sw));
414                         log.fatal("Failed to create role '" + roleName + "'");
415                         log.fatal(sw.toString());
416                     }
417                 }
418             }
419         }
420         if ( log.isInfoEnabled() ) {
421             log.info("Database security roles synchronized with deployment descriptor");
422         }
423     }
424 */

425
426     /**
427      * Sets the bean name of the SessionFactory to fetch from Spring's
428      * root application context. Default is "sessionFactory".
429      *
430      * @see #DEFAULT_SESSION_FACTORY_BEAN_NAME
431      */

432     public void setSessionFactoryBeanName(String JavaDoc sessionFactoryBeanName) {
433         this.sessionFactoryBeanName = sessionFactoryBeanName;
434     }
435
436     /**
437      * Returns the bean name of the SessionFactory to fetch from Spring's
438      * root application context.
439      *
440      * @return session factory bean name
441      */

442     protected String JavaDoc getSessionFactoryBeanName() {
443         return sessionFactoryBeanName;
444     }
445
446     /**
447      * Looks up the SessionFactory that this filter should use.
448      * <p>The default implementation looks for a bean with the specified name
449      * in Spring's root application context.
450      *
451      * @return the SessionFactory to use
452      * @see #getSessionFactoryBeanName
453      */

454     protected SessionFactory lookupSessionFactory() {
455         if ( log.isDebugEnabled() ) {
456             log.debug("Using session factory '" + getSessionFactoryBeanName() + "' for StartupListener");
457         }
458         WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
459         return (SessionFactory) wac.getBean(getSessionFactoryBeanName());
460     }
461
462     /**
463      * Gets a Session for the SessionFactory that this listener uses.
464      * Note that this just applies in single session mode!
465      * <p>The default implementation delegates to SessionFactoryUtils'
466      * getSession method and sets the Session's flushMode to NEVER.
467      * <p>Can be overridden in subclasses for creating a Session with a custom
468      * entity interceptor or JDBC exception translator.
469      *
470      * @param sessionFactory the SessionFactory that this listener uses
471      * @return the Session to use
472      * @throws org.springframework.dao.DataAccessResourceFailureException
473      * if the Session could not be created
474      * @see org.springframework.orm.hibernate3.SessionFactoryUtils#getSession(SessionFactory, boolean)
475      * @see org.hibernate.FlushMode#NEVER
476      */

477     protected Session getSession(SessionFactory sessionFactory)
478             throws DataAccessResourceFailureException {
479         Session session = SessionFactoryUtils.getSession(sessionFactory, true);
480         session.setFlushMode(FlushMode.NEVER);
481         return session;
482     }
483
484     /**
485      * Closes the given Session.
486      * Note that this just applies in single session mode!
487      * <p>The default implementation delegates to SessionFactoryUtils'
488      * closeSessionIfNecessary method.
489      * <p>Can be overridden in subclasses, e.g. for flushing the Session before
490      * closing it. See class-level javadoc for a discussion of flush handling.
491      * Note that you should also override getSession accordingly, to set
492      * the flush mode to something else than NEVER.
493      *
494      * @param session the Session used for filtering
495      * @param sessionFactory the SessionFactory that this filter uses
496      */

497     protected void closeSession(Session session, SessionFactory sessionFactory) {
498         SessionFactoryUtils.releaseSession(session, sessionFactory);
499     }
500
501 }
502
Popular Tags