org.grouter.common.hibernate.HibernateUtilContextAware.java Source code

Java tutorial

Introduction

Here is the source code for org.grouter.common.hibernate.HibernateUtilContextAware.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.grouter.common.hibernate;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Hashtable;

import org.hibernate.*;
import org.hibernate.cfg.*;
import org.apache.commons.logging.*;
import org.grouter.common.jndi.JNDIUtils;

import javax.naming.*;

/**
 * Basic Hibernate helper class for Hibernate configuration and bootstraping. It will hold multiple
 * sessionfactories in a map enabling switching between different datasources.
 * <p/>
 * <p/>
 * Use HibernateUtilContextAware.bootStrap(true) if you want to load the hibernate.cfg.xml file
 * AND any other configurations you have added using addSessionFactoryToMap(...). A bootstrap can only
 * happen once!
 * If you during runtime need to add or remove sessionfactories you must first see to that
 * HibernateUil is in a state of SHUTDOWN - by calling the shutdown() method. After that you can
 * addSessionFactoryToMap(...) and rebuildSessionFactory()
 *
 * @author Georges Polyzois
 * @see HibernateUtilContextAware for unit testing of this class.
 */
public class HibernateUtilContextAware {
    private static Log log = LogFactory.getLog(HibernateUtilContextAware.class);
    private final static Map<String, HibernateConfigItem> hibernateConfigMap = new HashMap<String, HibernateConfigItem>();
    private static HibernateConfigItem hibernateConfigItemDefault;

    // States indicate in what state we are currenlty in - some operations are prohibited depending on state.
    public enum STATE {
        NOTINITIALISED, INITIALISED, SHUTDOWN
    }

    private static STATE currentState = STATE.NOTINITIALISED;
    //private static boolean isBootstraped = false;

    /**
     * This method will load hibernate.cfg.xml if found in path and set that conifguration to the default configuration -
     * any other sessionfactories/configurations need to override and set the default flag to true
     * using addSessionFactoryToMap(...).
     * It will also load any other config settings for sessionfactories found in hibernateConfigMap.
     *
     * @param useHibernateCfgXmlFileOnPath if true load any found hibernate.cfg.xml
     */
    @SuppressWarnings({ "SameParameterValue" })
    public static void bootStrap(boolean useHibernateCfgXmlFileOnPath) {

        if (currentState == STATE.INITIALISED) {
            throw new IllegalStateException("You need to issue a shutdown before entering new configurations!!");
        }
        /*  if(isBootstraped)
        {
        log.info("Already bootstraped Hibernate - it is a one time only bootstrapping!");
        return;
        }*/
        if (useHibernateCfgXmlFileOnPath) {
            addSessionFactoryToMap("default", "hibernate.cfg.xml", true);

            //     isBootstraped = true;
            createSessionFactoriesFromConfigMap();
        }

    }

    /**
     * Set a new config item in the config Map. If setToDefault is true then we remove any prior default
     * sessionfactory from the config map - last default set will win.
     * <p/>
     * If you want to use a default hibernate.cfg.xml file then init HibernateUtil with:
     * addSessionFactoryToMap("default","hibernate.cfg.xml",true);
     *
     * @param sessionFactoryName name of the sessionfactory to add
     * @param hibernateCfgFile   path to config file
     * @param setToDefault       wether this facgtory should be the default one to use
     */
    public static void addSessionFactoryToMap(String sessionFactoryName, String hibernateCfgFile,
            boolean setToDefault) {
        if (currentState == STATE.INITIALISED) {
            throw new IllegalStateException("You need to issue a shutdown before entering new configurations!!");
        }
        HibernateConfigItem hibernateConfigItem = new HibernateConfigItem(sessionFactoryName, hibernateCfgFile,
                setToDefault);
        hibernateConfigMap.put(hibernateConfigItem.getId(), hibernateConfigItem);
    }

    /**
     * Set a new config item the config Map. If setToDefault is true then we remove any prior default
     * sessionfactory from the config map - last default set will win.
     *
     * @param sessionFactoryName name of the sessionfactory to add
     * @param hibernateConfig contains the configuration settings to this session factory
     * @param setToDefault    wether this facgtory should be the default one to use
     */
    @SuppressWarnings({ "SameParameterValue", "SameParameterValue" })
    public static void addSessionFactoryToMap(String sessionFactoryName, Configuration hibernateConfig,
            boolean setToDefault) {
        if (currentState == STATE.INITIALISED) {
            throw new IllegalStateException("You need to issue a shutdown before entering new configurations!!");
        }
        HibernateConfigItem hibernateConfigItem = new HibernateConfigItem(sessionFactoryName, hibernateConfig,
                setToDefault);
        hibernateConfigMap.put(hibernateConfigItem.getId(), hibernateConfigItem);
    }

    /**
     * Create session factories and configurations and store in hibernateConfigMap. On
     * completion we enter INITIALISED state.
     */
    private static void createSessionFactoriesFromConfigMap() {
        // read in all config and create session factories
        Iterator iter = hibernateConfigMap.keySet().iterator();
        while (iter.hasNext()) {
            SessionFactory sessionFactory;
            String key = (String) iter.next();
            HibernateConfigItem hibernateConfigItem = hibernateConfigMap.get(key);
            String file = hibernateConfigItem.getConfigFile();
            Configuration configuration;
            if (file == null) {
                log.info("Loading properties config and not from file ");
                configuration = hibernateConfigItem.getConfiguration();
            } else {
                log.info("Loading properties from : " + file);
                configuration = new Configuration();
                configuration = configuration.configure(file);
            }
            try {
                String sessionFactoryName = configuration.getProperty(Environment.SESSION_FACTORY_NAME);
                if (sessionFactoryName != null) {
                    log.debug("Looking up SessionFactory in JNDI with name : " + sessionFactoryName);
                    try {
                        Hashtable env = new Hashtable();
                        env.put(Context.INITIAL_CONTEXT_FACTORY, configuration.getProperty(Environment.JNDI_CLASS));
                        env.put(Context.URL_PKG_PREFIXES, configuration.getProperty(Environment.JNDI_PREFIX));
                        env.put(Context.PROVIDER_URL, configuration.getProperty(Environment.JNDI_URL));
                        Context context = new InitialContext(env);
                        JNDIUtils.printJNDI(context, log);
                        sessionFactory = (SessionFactory) context.lookup(sessionFactoryName);
                        if (sessionFactory == null) {
                            throw new IllegalStateException(
                                    "SessionFactory from JNDI lookup returned a null implemenation  using file : "
                                            + file);
                        }
                    } catch (NamingException ex) {
                        log.error("Failed looking up sessinfactory : " + sessionFactoryName, ex);
                        throw new RuntimeException(ex);
                    }
                } else {
                    sessionFactory = configuration.buildSessionFactory();
                    if (sessionFactory == null) {
                        throw new IllegalStateException(
                                "SessionFactory could not be createed from the configuration using file : " + file);
                    }
                }
                hibernateConfigItem.setConfiguration(configuration);
                hibernateConfigItem.setSessionFactory(sessionFactory);
                // We need to have a default sessionfactory / configuration
                if (hibernateConfigItem.isDeafult()) {
                    hibernateConfigItemDefault = hibernateConfigItem;
                }
                // setInterceptor(configuration, null);
                // hibernateConfigMap.put(key)
            } catch (Throwable ex) {
                log.error("Failed initializing from configuration.", ex);
                throw new ExceptionInInitializerError(ex);
            }
        }
        currentState = STATE.INITIALISED;
        log.info("Entered state : " + currentState);
    }

    /**
     * Returns the Hibernate configuration for a session factory.
     *
     * @param sessionFactoryName the name of the sessionfactory
     * @return Configuration
     */
    public static Configuration getConfiguration(String sessionFactoryName) {
        HibernateConfigItem hibernateConfigItem = getConfigItemFromMap(sessionFactoryName);
        return hibernateConfigItem.getConfiguration();
    }

    /**
     * Returns the default Hibernate configuration.
     *
     * @return Configuration
     */
    public static Configuration getConfiguration() {
        return hibernateConfigItemDefault.getConfiguration();
    }

    /**
     * Pull out the configitem or throw runtime exception if not found.
     *
     * @param sessionFactoryName the name of the sessionfactory
     * @return HibernateConfigItem
     */
    private static HibernateConfigItem getConfigItemFromMap(String sessionFactoryName) {
        HibernateConfigItem hibernateConfigItem;
        if (hibernateConfigMap.containsKey(sessionFactoryName)) {
            hibernateConfigItem = hibernateConfigMap.get(sessionFactoryName);
        } else {
            throw new IllegalStateException("Configuration not available for : " + sessionFactoryName);
        }
        return hibernateConfigItem;
    }

    /**
     * Returns the global SessionFactory.
     *
     * @param sessionFactoryName the name of the sessionfactory
     * @return SessionFactory
     */
    @SuppressWarnings({ "SameParameterValue" })
    public static SessionFactory getSessionFactory(String sessionFactoryName) {
        HibernateConfigItem hibernateConfigItem = getConfigItemFromMap(sessionFactoryName);
        SessionFactory sf = hibernateConfigItem.getSessionFactory();
        if (sf == null) {
            throw new IllegalStateException("No sessionfactory found for : " + sessionFactoryName);
        }
        return sf;
    }

    /**
     * Returns the default SessionFactory. If in SHUTDOWN state a runtime exception is thrown.
     *
     * @return SessionFactory
     * @throws IllegalStateException if currentstate is SHUTDOWN
     */
    public static SessionFactory getSessionFactory() {
        if (currentState == STATE.SHUTDOWN) {
            throw new IllegalStateException("Current state : " + currentState
                    + ". You need to call rebuildSessionFactory before calling this method!!");
        }
        return hibernateConfigItemDefault.getSessionFactory();
    }

    /**
     * Give an indication of how many configuraations we have set up.
     *
     * @return int
     */
    public static int getHibernateConfigMapSize() {
        return hibernateConfigMap.size();
    }

    /**
     * Closes the current SessionFactory and releases all resources.
     * <p/>
     * You need to call rebuildSessionFactory() to reinit the HibernateUtil's sessionfactories in the
     * internal map of sessionfactories.
     *
     * @param removeAllConfigFromInternalMap if true it will clear the internal map of sessionfactories and config
     */

    public static void shutdown(boolean removeAllConfigFromInternalMap) {
        log.debug("Shutting down Hibernate.");
        Iterator iter = hibernateConfigMap.values().iterator();
        while (iter.hasNext()) {
            HibernateConfigItem hibernateConfigItem = (HibernateConfigItem) iter.next();
            log.debug("Closing sessionfactory : " + hibernateConfigItem.getId());
            SessionFactory sf = hibernateConfigItem.getSessionFactory();
            if (sf != null) {
                sf.close();
            }
            sf = null;
            log.debug("Closed sessionfactory : " + hibernateConfigItem.getId());
        }
        if (removeAllConfigFromInternalMap) {
            log.info("Removing all configurations from the internal hibernate config map");
            hibernateConfigMap.clear();
        }
        hibernateConfigItemDefault = null;
        currentState = STATE.SHUTDOWN;
        log.info("Entered state : " + currentState);
    }

    /**
     * Rebuild the SessionFactory with the static Configuration.
     * 
     * This method also closes the old SessionFactory before, if still open. Note that this method should only be used
     * with static SessionFactory management, not with JNDI or any other external registry.
     */
    public static void rebuildSessionFactory() {
        log.debug("Using current Configuration for rebuild.");
        synchronized (hibernateConfigMap) {
            createSessionFactoriesFromConfigMap();
        }
    }

    /**
     * Return current state.
     *
     * @return the current state of HibernateUtil
     */
    public static STATE getCurrentState() {
        return currentState;
    }

    /**
     * These items are stored withing the HibernateUtil map of configurations with sessionfactories.
     */
    public static class HibernateConfigItem {
        private String id;
        private String configFile;
        private Configuration configuration;
        private SessionFactory sessionFactory;
        private boolean isDeafult;

        /**
         * Constructor.
         *
         * @param id         the key or id in the map holding the items
         * @param configFile a name of a hibernate config file
         * @param isDeafult  wether to treat this as the default item in the internal map of HibernateUtil
         */
        public HibernateConfigItem(String id, String configFile, boolean isDeafult) {
            this.id = id;
            this.configFile = configFile;
            this.isDeafult = isDeafult;
        }

        /**
         * @param id            the key or id in the map holding the items
         * @param configuration a Hibernate configuration instance
         * @param isDeafult     wether to treat this as the default item in the internal map of HibernateUtil
         */
        public HibernateConfigItem(String id, Configuration configuration, boolean isDeafult) {
            this.id = id;
            this.isDeafult = isDeafult;
            this.configuration = configuration;
        }

        /**
         * Wether this is a default item or not.
         *
         * @return wether this is the dafault or not.
         */
        public boolean isDeafult() {
            return isDeafult;
        }

        /**
         * Set as default.
         *
         * @param deafult  set this to default
         */
        public void setDeafult(boolean deafult) {
            isDeafult = deafult;
        }

        /**
         * @return Returns the configFile.
         */
        public String getConfigFile() {
            return configFile;
        }

        /**
         * @return Returns the configuration.
         */
        public Configuration getConfiguration() {
            return configuration;
        }

        /**
         * @param configuration The configuration to set.
         */
        public void setConfiguration(Configuration configuration) {
            this.configuration = configuration;
        }

        /**
         * @return Returns the sessionFactory.
         */
        public SessionFactory getSessionFactory() {
            return sessionFactory;
        }

        /**
         * @param sessionFactory The sessionFactory to set.
         */
        public void setSessionFactory(SessionFactory sessionFactory) {
            this.sessionFactory = sessionFactory;
        }

        /**
         * @return Returns the id.
         */
        public String getId() {
            return id;
        }

    }
}