001    /*****************************************************************************
002     * Copyright (c) PicoContainer Organization. All rights reserved.            *
003     * ------------------------------------------------------------------------- *
004     * The software in this package is published under the terms of the BSD      *
005     * style license a copy of which has been included with this distribution in *
006     * the license.html file.                                                    *
007     *                                                                           *
008     * Idea by Rachel Davies, Original code by Aslak Hellesoy and Paul Hammant   *
009     *****************************************************************************/
010    package org.nanocontainer.persistence.hibernate.classic;
011    
012    import java.sql.Connection;
013    import net.sf.hibernate.HibernateException;
014    import net.sf.hibernate.Interceptor;
015    import net.sf.hibernate.Session;
016    import net.sf.hibernate.SessionFactory;
017    import org.picocontainer.PicoInitializationException;
018    
019    /**
020     * session delegator with failover behaviour in case of hibernate exception. old session is disposed and new one is
021     * obtained transparently. session creation is done lazily.
022     * 
023     * @author Konstantin Pribluda
024     * @author Jose Peleteiro
025     * @version $Revision: 2043 $
026     */
027    public class FailoverSessionDelegator extends SessionDelegator {
028    
029            Interceptor interceptor = null;
030            Session session = null;
031            SessionFactory sessionFactory;
032    
033            /**
034             * @param sessionFactory session factory to obtain session from 
035             */
036            public FailoverSessionDelegator(SessionFactory sessionFactory) {
037                    setSessionFactory(sessionFactory);
038            }
039    
040            /**
041             * @param sessionFactory session factory to obtain session from 
042             * @param exceptionHandler Exception handler component to use with created session
043             */
044            public FailoverSessionDelegator(SessionFactory sessionFactory, HibernateExceptionHandler exceptionHandler) {
045                    super(exceptionHandler);
046                    setSessionFactory(sessionFactory);
047            }
048    
049            /**
050             * @param sessionFactory sessionf actory to obtain session from
051             * @param interceptor interceptor to use with created session
052             */
053            public FailoverSessionDelegator(SessionFactory sessionFactory, Interceptor interceptor) {
054                    this(sessionFactory);
055                    setInterceptor(interceptor);
056            }
057    
058            /**
059             * @param sessionFactory sessionf actory to obtain session from
060             * @param interceptor interceptor to use with created session
061             * @param exceptionHandler Exception handler component to use with created session
062             */
063            public FailoverSessionDelegator(SessionFactory sessionFactory, Interceptor interceptor, HibernateExceptionHandler exceptionHandler) {
064                    this(sessionFactory, exceptionHandler);
065                    setInterceptor(interceptor);
066            }
067    
068            public Connection close() throws HibernateException {
069                    Connection retval = null;
070                    try {
071                            retval = getDelegatedSession().close();
072                    } catch (HibernateException ex) {
073                            session = null;
074                            throw ex;
075                    } finally {
076                            session = null;
077                    }
078    
079                    return retval;
080            }
081    
082            /**
083             * obtain hibernate session in lazy way. use interceptor if configured
084             */
085            public Session getDelegatedSession() {
086                    if (session == null) {
087                            try {
088                                    session = interceptor == null ? sessionFactory.openSession() : sessionFactory.openSession(interceptor);
089                            } catch (HibernateException ex) {
090                                    throw new PicoInitializationException(ex);
091                            }
092                    }
093    
094                    return session;
095            }
096    
097            public Interceptor getInterceptor() {
098                    return interceptor;
099            }
100    
101            public SessionFactory getSessionFactory() {
102                    return sessionFactory;
103            }
104    
105            public void invalidateDelegatedSession() throws HibernateException {
106                    if (session != null) {
107                            try {
108                                    session.clear();
109                                    session.close();
110                            } catch (HibernateException ex) {
111                                    session = null;
112                                    throw ex;
113                            } finally {
114                                    session = null;
115                            }
116                    }
117            }
118    
119            public void setInterceptor(Interceptor interceptor) {
120                    this.interceptor = interceptor;
121            }
122    
123            public void setSessionFactory(SessionFactory sessionFactory) {
124                    this.sessionFactory = sessionFactory;
125            }
126    }