001    /* Copyright 2006-2009 the original author or authors.
002     *
003     * Licensed under the Apache License, Version 2.0 (the "License");
004     * you may not use this file except in compliance with the License.
005     * You may obtain a copy of the License at
006     *
007     *      http://www.apache.org/licenses/LICENSE-2.0
008     *
009     * Unless required by applicable law or agreed to in writing, software
010     * distributed under the License is distributed on an "AS IS" BASIS,
011     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012     * See the License for the specific language governing permissions and
013     * limitations under the License.
014     */
015    package org.codehaus.groovy.grails.plugins.springsecurity;
016    
017    import org.apache.log4j.Logger;
018    import org.hibernate.Session;
019    import org.hibernate.SessionFactory;
020    import org.springframework.orm.hibernate3.SessionFactoryUtils;
021    import org.springframework.orm.hibernate3.SessionHolder;
022    import org.springframework.transaction.support.TransactionSynchronizationManager;
023    import org.springframework.web.context.support.WebApplicationObjectSupport;
024    
025    /**
026     * Grails Web Application Object Support.
027     *
028     * @author T.Yamamoto
029     * @author <a href='mailto:beckwithb@studentsonly.com'>Burt Beckwith</a>
030     */
031    public abstract class GrailsWebApplicationObjectSupport extends WebApplicationObjectSupport {
032    
033            private final Logger _log = Logger.getLogger(getClass());
034    
035            private SessionFactory _sessionFactory;
036    
037            /**
038             * Dependency injection for Hibernate session factory.
039             * @param sessionFactory  the factory
040             */
041            public void setSessionFactory(final SessionFactory sessionFactory) {
042                    _sessionFactory = sessionFactory;
043            }
044    
045            /**
046             * Holds the session created or existing session and a flag indicating whether it was
047             * existing (so we know whether to close it or not).
048             */
049            public static class SessionContainer {
050                    private final Session _session;
051                    private final boolean _existingSession;
052    
053                    private SessionContainer(final Session session, final boolean existingSession) {
054                            _session = session;
055                            _existingSession = existingSession;
056                    }
057    
058                    /**
059                     * Get the session.
060                     * @return  the session
061                     */
062                    public Session getSession() {
063                            return _session;
064                    }
065            }
066    
067            /**
068             * Set up hibernate session.
069             * @return  the session container, which holds the session and a boolean indicating if the session was pre-existing
070             */
071            protected SessionContainer setUpSession() {
072                    SessionFactory sessionFactory = getSessionFactory();
073    
074                    Session session;
075                    boolean existing;
076                    if (TransactionSynchronizationManager.hasResource(sessionFactory)) {
077                            _log.debug("Session already has transaction attached");
078                            existing = true;
079                            session = ((SessionHolder)TransactionSynchronizationManager.getResource(sessionFactory)).getSession();
080                    }
081                    else {
082                            _log.debug("Session does not have transaction attached... Creating new one");
083                            existing = false;
084                            session = SessionFactoryUtils.getSession(sessionFactory, true);
085                            SessionHolder sessionHolder = new SessionHolder(session);
086                            TransactionSynchronizationManager.bindResource(sessionFactory, sessionHolder);
087                    }
088    
089                    return new SessionContainer(session, existing);
090            }
091    
092            /**
093             * Release Session.
094             */
095            protected void releaseSession(final SessionContainer session) {
096                    if (session._existingSession) {
097                            return;
098                    }
099    
100                    SessionFactory sessionFactory = getSessionFactory();
101                    SessionHolder sessionHolder = (SessionHolder)TransactionSynchronizationManager.unbindResource(sessionFactory);
102                    SessionFactoryUtils.releaseSession(sessionHolder.getSession(), sessionFactory);
103                    _log.debug("Session released");
104            }
105    
106            private SessionFactory getSessionFactory() {
107                    if (_sessionFactory == null) {
108                            // should be set via DI, but for backwards compatibility lookup the standard bean
109                            _sessionFactory  = (SessionFactory)getWebApplicationContext().getBean("sessionFactory");
110                    }
111                    return _sessionFactory;
112            }
113    }