/** * Copyright (C) 2008-2010, Squale Project - http://www.squale.org * * This file is part of Squale. * * Squale is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or any later version. * * Squale is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Squale. If not, see <http://www.gnu.org/licenses/>. */ /* * Cree le 31 janv. 05 */ package org.squale.jraf.provider.persistence.hibernate; import java.io.IOException; import java.util.Iterator; import java.util.Map; import java.util.StringTokenizer; import java.util.WeakHashMap; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.hibernate.HibernateException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.squale.jraf.bootstrap.locator.ProviderLocator; import org.squale.jraf.commons.exception.JrafPersistenceException; import org.squale.jraf.commons.exception.JrafRuntimeException; import org.squale.jraf.spi.persistence.IPersistenceProvider; /** * <p>Project: JRAF * <p>Title : HibernateFilter</p> * <p>Description : </p> * <p>Copyright : Copyright (c) 2005</p> * */ public class HibernateFilter implements Filter { /** constante d'initialisation pour les providers de persistance */ public final static String PERSISTENCE_PROVIDER_INIT = "persistenceProvider"; /** cle pour stocker une session longue dans la session HTTP */ public final static String SESSIONS_KEY = "JRAF_PERSISTENCEPROVIDER_"; /** logger */ private final static Log log = LogFactory.getLog(HibernateFilter.class); /** * map de providers */ private Map providersMap = new WeakHashMap(); /** * */ public HibernateFilter() { super(); } /* (non-Javadoc) * @see javax.servlet.Filter#destroy() */ public void destroy() { } /* (non-Javadoc) * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain) */ public void doFilter( ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { try { // pre-process if (log.isDebugEnabled()) { log.debug("preprocess..."); } preProcess(request, response); // execution de la chaine de filtre chain.doFilter(request, response); // post-process if (log.isDebugEnabled()) { log.debug("postprocess..."); } postProcess(request, response); } catch (IOException ioe) { log.error(ioe); throw ioe; } catch (ServletException se) { log.error(se); throw se; } finally { // nothing to do } } /** * Pre-traitement d'une requete HTTP */ public void preProcess(ServletRequest request, ServletResponse response) throws IOException, ServletException { SessionImpl session = null; Iterator iterator = getProvidersMap().entrySet().iterator(); Map.Entry entry = null; PersistenceProviderImpl persistenceProvider = null; String providerName = null; HttpServletRequest httpRequest = (HttpServletRequest) request; HttpSession httpSession = null; // pour chaque provider while (iterator.hasNext()) { entry = (Map.Entry) iterator.next(); providerName = (String) entry.getKey(); persistenceProvider = (PersistenceProviderImpl) entry.getValue(); if (log.isDebugEnabled()) { log.debug("providerName=" + providerName); } // cas thread local session et longue session if (persistenceProvider.isThreadLocalSession() && persistenceProvider.isLongSession()) { if (log.isDebugEnabled()) { log.debug("Cas thread local session et session longue..."); } httpSession = httpRequest.getSession(); if (log.isDebugEnabled()) { log.debug("Recuperation de la session..."); } session = (SessionImpl) httpSession.getAttribute( SESSIONS_KEY + providerName); if (session != null) { if (log.isDebugEnabled()) { log.debug("Session existante..."); log.debug( "Mise de la session dans le thread local storage..."); } ThreadLocal tl = new ThreadLocal(); tl.set(session); persistenceProvider.setThreadLocal(tl); } else { if (log.isDebugEnabled()) { log.debug("Session non existante..."); log.debug("Elle sera creee en cas d'appel..."); } } } } // rien a faire par defaut } /** * Post-traitement d'une requete HTTP */ public void postProcess(ServletRequest request, ServletResponse response) throws IOException, ServletException { Iterator iterator = getProvidersMap().entrySet().iterator(); Map.Entry entry = null; PersistenceProviderImpl persistenceProvider = null; String providerName = null; HttpServletRequest httpRequest = (HttpServletRequest) request; HttpSession httpSession = null; SessionImpl session = null; while (iterator.hasNext()) { entry = (Map.Entry) iterator.next(); providerName = (String) entry.getKey(); persistenceProvider = (PersistenceProviderImpl) entry.getValue(); // cas thread local session if (persistenceProvider.isThreadLocalSession()) { if (log.isDebugEnabled()) { log.debug("Cas Thread Local Session..."); } if (persistenceProvider.getThreadLocal() != null) { // cas thread local existe if (log.isDebugEnabled()) { log.debug("Cas thread local existe..."); } session = (SessionImpl) persistenceProvider .getThreadLocal() .get(); // cas session non null if (session != null) { if (log.isDebugEnabled()) { log.debug("Cas session existante..."); } // cas transaction automatique + transaction existante if (persistenceProvider.isAutomaticTransaction() && session.isInTransaction()) { if (log.isDebugEnabled()) { log.debug( "Cas transaction automatique existante..."); } if (session.isValid()) { try { if (log.isDebugEnabled()) { log.debug( "Commit de la transaction..."); } session.commitTransactionWithoutClose(); if (log.isDebugEnabled()) { log.debug("Commit OK"); } } catch (JrafPersistenceException e) { String message = "Probleme lors de la validation de la transaction"; log.error(message, e); if (log.isDebugEnabled()) { log.debug( "Rollback de la transaction..."); } session.rollbackTransactionWithoutClose(); // on lance une runtime exception throw new JrafRuntimeException(message, e); } } else { // cas de session non valide (une exception a ete levee durant le traitement) if (log.isDebugEnabled()) { log.debug( "invalid session : rollback de la transaction ..."); } session.rollbackTransactionWithoutClose(); } } // cas session longue if (persistenceProvider.isLongSession()) { if (log.isDebugEnabled()) { log.debug("Cas de la session longue..."); } try { // si la session est connectee et ouverte if (session.isConnected() && session.isOpen()) { if (session.isValid()) { if (log.isDebugEnabled()) { log.debug("Flush de la session..."); } session.getSession().flush(); } else { if (log.isDebugEnabled()) { log.debug( "invalid session : clear ..."); } } if (log.isDebugEnabled()) { log.debug( "Deconnexion de la session..."); } // Depsuis hibernate 3 plus besoin de faire de reconnect et disconnect // session.getSession().disconnect(); } } catch (HibernateException e) { String message = "Probleme lors du flush/deconnexion de la session longue"; log.error(message, e); if (log.isDebugEnabled()) { log.debug("On reinitialise la session..."); } session.clear(); // on lance une runtime exception throw new JrafRuntimeException(message, e); } finally { if (log.isDebugEnabled()) { log.debug( "On attache la session dans la session http..."); } httpRequest.getSession().setAttribute( SESSIONS_KEY + providerName, session); if (log.isDebugEnabled()) { log.debug("On vide le thread local..."); } persistenceProvider.getThreadLocal().set(null); } } // cas thread local session sans session longue else { try { if (log.isDebugEnabled()) { log.debug("closing session..."); } // si la session est connectee et ouverte if (session.isConnected() && session.isOpen()) { if (session.isValid()) { // flush de la session if (log.isDebugEnabled()) { log.debug("flush session ..."); } session.flush(); } else { if (log.isDebugEnabled()) { log.debug("invalid session : clear session ..."); } session.clear(); } // fermeture de la session if (log.isDebugEnabled()) { log.debug("close session ..."); } session.getSession().close(); } } catch (Exception e) { String message = "Probleme lors de la fermeture de la session"; log.error(message, e); // on lance une runtime exception throw new JrafRuntimeException(message, e); } finally { if (log.isDebugEnabled()) { log.debug("On vide le thread local..."); } // persistenceProvider.setThreadLocal(null); persistenceProvider.getThreadLocal().set(null); } } } } } } } /* (non-Javadoc) * @see javax.servlet.Filter#init(javax.servlet.FilterConfig) */ public void init(FilterConfig filterConfig) throws ServletException { // providers String providers = filterConfig.getInitParameter(PERSISTENCE_PROVIDER_INIT); if (providers != null) { // map de providers Map mProviders = getProviders(providers); // on fixe la map de providers setProvidersMap(mProviders); } else { log.debug("Aucun provider en parametre"); } } /** Retourne une map de providers * @param providers * @return */ protected final Map getProviders(String providers) { // pas de providers on retourne null if (providers == null) { return null; } StringTokenizer st = new StringTokenizer(providers, ","); String providerName; IPersistenceProvider persistenceProvider = null; Map m = new WeakHashMap(); while (st.hasMoreTokens()) { providerName = st.nextToken(); persistenceProvider = (IPersistenceProvider) ProviderLocator.getProvider( providerName); if (persistenceProvider != null) { m.put(providerName, persistenceProvider); } } return m; } /** * @return */ public Map getProvidersMap() { return providersMap; } /** * @param map */ public void setProvidersMap(Map map) { providersMap = map; } }