package struts;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;

import net.sf.hibernate.HibernateException;
import net.sf.hibernate.Session;
import net.sf.hibernate.SessionFactory;
import net.sf.hibernate.cfg.Configuration;

import org.apache.struts.action.ActionServlet;
import org.apache.struts.action.PlugIn;
import org.apache.struts.config.ModuleConfig;

/**
 * Initialize the Hibernate SessionFactory for this project
 * as an application scope object.
 *
 * @author Ted Husted
 * @version $Revision: 1.2 $ $Date: 2007/11/27 16:36:04 $
 */
public class HibernatePlugIn implements PlugIn {

    /**
     * A field to store the reference to our SessionFactory.
     * Can close and dispose if not null.
     */
    private static SessionFactory sf;

    /**
     * A public identifer for the session factory,
     * kept in application ("global") scope
     * ["HIBERNATE_SESSION_FACTORY"].
     */
    public static String SESSION_FACTORY = "HIBERNATE_SESSION_FACTORY";

    /**
     * Fetch the SessionFactory from application scope.
     * @param request The requeste we are servicing
     * @return The SessionFactory for this application session
     * @throws HibernateException
     */
    public static SessionFactory sessionFactory(HttpServletRequest request)
            throws HibernateException {
        Object sf = request.getSession().getServletContext().getAttribute(SESSION_FACTORY);
        if (null == sf) {
        	try {
				sf = konfigurujHibernate(request.getSession().getServletContext());
			} catch (ServletException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
        }
        return (SessionFactory) sf;
    }


    /**
     * Open a new session with the application-scope SessionFactory.
     * Session is not retained, only returned.
     *
     * @param request The requeset we are servicing
     * @return An open session
     * @throws HibernateException
     */
    public static Session open(HttpServletRequest request) throws HibernateException {
        return sessionFactory(request).openSession();
    }

    /**
     * The classes with mappings to add to the Configuration are enumerated here.
     * There should be a "${class}.hbm.xml" mapping file for each class
     * stored with each compiled class file.
     * <p>
     * To complete the Hibernate setup, there must be a valid "hiberate.properties"
     * file under the "classes" folder (root of the classpath),
     * which specifies the details of the database hookup.
     * <p>
     * The mapping documents and properties file is all that Hibernate requires.
     * <p>
     * A JDBC Driver is not included in this distribution and *must* be
     * available on your server's or container's classpath
     * (e.g., the Tomcat common/lib directory).
     *
     * @return A Configuration object
     * @throws net.sf.hibernate.MappingException if any the mapping documents can be rendered.
     */
    private static final Configuration createConfiguration()
            throws HibernateException {
        return new Configuration().configure();
    }

    public void init(ActionServlet servlet, ModuleConfig config)
            throws ServletException {

    }


	private static SessionFactory konfigurujHibernate(ServletContext servletContext) throws ServletException {
		SessionFactory exists = (SessionFactory)
                servletContext.getAttribute(SESSION_FACTORY);
        if (null != exists) return exists; // already got one

        try {
            sf = createConfiguration().buildSessionFactory();
        } catch (HibernateException e) {
            e.printStackTrace();
            throw new ServletException(e);
        }

        servletContext.setAttribute(SESSION_FACTORY, sf);
        
        return sf;
	}

    public void destroy() {
        if (null != sf) {
            try {
                sf.close();
            } catch (HibernateException e) {
                // too late now
            }
        }
        sf = null;
    }

}
